<div dir="ltr">Ah, sorry - I think I tested that first & found it was used. I forget what the particular use was - but should be easy to reproduce & hopefully there's some good fix for it. Happy to help with the implementation or ideas about how to address it if you like.</div><br><div class="gmail_quote"><div dir="ltr">On Thu, Mar 29, 2018 at 10:15 AM Philip Reames <<a href="mailto:listmail@philipreames.com">listmail@philipreames.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div text="#000000" bgcolor="#FFFFFF">
    <p><br>
    </p>
    <br>
    <div class="m_-6492984690386630205moz-cite-prefix">On 03/28/2018 04:16 PM, David Blaikie
      wrote:<br>
    </div>
    <blockquote type="cite">
      <div dir="ltr"><br>
        <br>
        <div class="gmail_quote">
          <div dir="ltr">On Tue, Mar 20, 2018 at 10:11 AM Philip Reames
            via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author:
            reames<br>
            Date: Tue Mar 20 10:09:21 2018<br>
            New Revision: 328004<br>
            <br>
            URL: <a href="http://llvm.org/viewvc/llvm-project?rev=328004&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=328004&view=rev</a><br>
            Log:<br>
            Add an analysis printer for must execute reasoning<br>
            <br>
            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.<br>
            <br>
            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.)<br>
            <br>
            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.<br>
            <br>
            Differential Revision: <a href="https://reviews.llvm.org/D44524" rel="noreferrer" target="_blank">https://reviews.llvm.org/D44524</a><br>
            <br>
            <br>
            Added:<br>
                llvm/trunk/lib/Analysis/MustExecute.cpp<br>
                llvm/trunk/test/Analysis/MustExecute/<br>
                llvm/trunk/test/Analysis/MustExecute/loop-header.ll<br>
            Modified:<br>
                llvm/trunk/include/llvm/Analysis/Passes.h<br>
                llvm/trunk/include/llvm/InitializePasses.h<br>
                llvm/trunk/include/llvm/LinkAllPasses.h<br>
                llvm/trunk/lib/Analysis/Analysis.cpp<br>
                llvm/trunk/lib/Analysis/CMakeLists.txt<br>
            <br>
            Modified: llvm/trunk/include/llvm/Analysis/Passes.h<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=328004&r1=328003&r2=328004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=328004&r1=328003&r2=328004&view=diff</a><br>
==============================================================================<br>
            --- llvm/trunk/include/llvm/Analysis/Passes.h (original)<br>
            +++ llvm/trunk/include/llvm/Analysis/Passes.h Tue Mar 20
            10:09:21 2018<br>
            @@ -96,6 +96,14 @@ namespace llvm {<br>
               //<br>
               FunctionPass *createMemDerefPrinter();<br>
            <br>
            + 
//===--------------------------------------------------------------------===//<br>
            +  //<br>
            +  // createMustExecutePrinter - This pass collects
            information about which<br>
            +  // instructions within a loop are guaranteed to execute
            if the loop header is<br>
            +  // entered and prints it with -analyze.<br>
            +  //<br>
            +  FunctionPass *createMustExecutePrinter();<br>
            +<br>
             }<br>
            <br>
             #endif<br>
            <br>
            Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=328004&r1=328003&r2=328004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=328004&r1=328003&r2=328004&view=diff</a><br>
==============================================================================<br>
            --- llvm/trunk/include/llvm/InitializePasses.h (original)<br>
            +++ llvm/trunk/include/llvm/InitializePasses.h Tue Mar 20
            10:09:21 2018<br>
            @@ -268,6 +268,7 @@ void initializeMergedLoadStoreMotionLega<br>
             void initializeMetaRenamerPass(PassRegistry&);<br>
             void
            initializeModuleDebugInfoPrinterPass(PassRegistry&);<br>
             void
            initializeModuleSummaryIndexWrapperPassPass(PassRegistry&);<br>
            +void initializeMustExecutePrinterPass(PassRegistry&);<br>
             void
            initializeNameAnonGlobalLegacyPassPass(PassRegistry&);<br>
             void
            initializeNaryReassociateLegacyPassPass(PassRegistry&);<br>
             void initializeNewGVNLegacyPassPass(PassRegistry&);<br>
            <br>
            Modified: llvm/trunk/include/llvm/LinkAllPasses.h<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=328004&r1=328003&r2=328004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=328004&r1=328003&r2=328004&view=diff</a><br>
==============================================================================<br>
            --- llvm/trunk/include/llvm/LinkAllPasses.h (original)<br>
            +++ llvm/trunk/include/llvm/LinkAllPasses.h Tue Mar 20
            10:09:21 2018<br>
            @@ -207,6 +207,7 @@ namespace {<br>
                   (void) llvm::createRewriteSymbolsPass();<br>
                   (void) llvm::createStraightLineStrengthReducePass();<br>
                   (void) llvm::createMemDerefPrinter();<br>
            +      (void) llvm::createMustExecutePrinter();<br>
                   (void) llvm::createFloat2IntPass();<br>
                   (void)
            llvm::createEliminateAvailableExternallyPass();<br>
                   (void) llvm::createScalarizeMaskedMemIntrinPass();<br>
            <br>
            Modified: llvm/trunk/lib/Analysis/Analysis.cpp<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Analysis.cpp?rev=328004&r1=328003&r2=328004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Analysis.cpp?rev=328004&r1=328003&r2=328004&view=diff</a><br>
==============================================================================<br>
            --- llvm/trunk/lib/Analysis/Analysis.cpp (original)<br>
            +++ llvm/trunk/lib/Analysis/Analysis.cpp Tue Mar 20 10:09:21
            2018<br>
            @@ -65,6 +65,7 @@ void llvm::initializeAnalysis(PassRegist<br>
               initializeMemoryDependenceWrapperPassPass(Registry);<br>
               initializeModuleDebugInfoPrinterPass(Registry);<br>
               initializeModuleSummaryIndexWrapperPassPass(Registry);<br>
            +  initializeMustExecutePrinterPass(Registry);<br>
               initializeObjCARCAAWrapperPassPass(Registry);<br>
             
             initializeOptimizationRemarkEmitterWrapperPassPass(Registry);<br>
               initializePostDominatorTreeWrapperPassPass(Registry);<br>
            <br>
            Modified: llvm/trunk/lib/Analysis/CMakeLists.txt<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=328004&r1=328003&r2=328004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=328004&r1=328003&r2=328004&view=diff</a><br>
==============================================================================<br>
            --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)<br>
            +++ llvm/trunk/lib/Analysis/CMakeLists.txt Tue Mar 20
            10:09:21 2018<br>
            @@ -58,6 +58,7 @@ add_llvm_library(LLVMAnalysis<br>
               MemorySSAUpdater.cpp<br>
               ModuleDebugInfoPrinter.cpp<br>
               ModuleSummaryAnalysis.cpp<br>
            +  MustExecute.cpp<br>
               ObjCARCAliasAnalysis.cpp<br>
               ObjCARCAnalysisUtils.cpp<br>
               ObjCARCInstKind.cpp<br>
            <br>
            Added: llvm/trunk/lib/Analysis/MustExecute.cpp<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MustExecute.cpp?rev=328004&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MustExecute.cpp?rev=328004&view=auto</a><br>
==============================================================================<br>
            --- llvm/trunk/lib/Analysis/MustExecute.cpp (added)<br>
            +++ llvm/trunk/lib/Analysis/MustExecute.cpp Tue Mar 20
            10:09:21 2018<br>
            @@ -0,0 +1,102 @@<br>
            +//===- MustExecute.cpp - Printer for isGuaranteedToExecute
            ----------------===//<br>
            +//<br>
            +//                     The LLVM Compiler Infrastructure<br>
            +//<br>
            +// This file is distributed under the University of
            Illinois Open Source<br>
            +// License. See LICENSE.TXT for details.<br>
            +//<br>
+//===----------------------------------------------------------------------===//<br>
            +<br>
            +#include "llvm/Analysis/LoopInfo.h"<br>
            +#include "llvm/Analysis/Passes.h"<br>
            +#include "llvm/Analysis/ValueTracking.h"<br>
            +#include "llvm/IR/DataLayout.h"<br>
            +#include "llvm/IR/InstIterator.h"<br>
            +#include "llvm/IR/LLVMContext.h"<br>
            +#include "llvm/IR/Module.h"<br>
            +#include "llvm/Support/ErrorHandling.h"<br>
            +#include "llvm/Support/raw_ostream.h"<br>
            +#include "llvm/Transforms/Utils/LoopUtils.h"<br>
          </blockquote>
          <div><br>
            This looks like a circular/invalid dependency? Transforms
            depend on Analysis, not the other way around?<br>
            <br>
            Would be great to get this fixed - happy to help, if you've
            some ideas.<br>
            <br>
            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?)<br>
          </div>
        </div>
      </div>
    </blockquote></div><div text="#000000" bgcolor="#FFFFFF">
    I think this is just a stale header include.  I'm building to
    confirm now and if so will remove it.  <br></div><div text="#000000" bgcolor="#FFFFFF">
    <blockquote type="cite">
      <div dir="ltr">
        <div class="gmail_quote">
          <div> </div>
          <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
            +using namespace llvm;<br>
            +<br>
            +namespace {<br>
            +  struct MustExecutePrinter : public FunctionPass {<br>
            +    DenseMap<Value*, SmallVector<Loop*, 4> >
            MustExec;<br>
            +    SmallVector<Value *, 4> Ordering;<br>
            +<br>
            +    static char ID; // Pass identification, replacement for
            typeid<br>
            +    MustExecutePrinter() : FunctionPass(ID) {<br>
            +     
            initializeMustExecutePrinterPass(*PassRegistry::getPassRegistry());<br>
            +    }<br>
            +    void getAnalysisUsage(AnalysisUsage &AU) const
            override {<br>
            +      AU.setPreservesAll();<br>
            +      AU.addRequired<DominatorTreeWrapperPass>();<br>
            +      AU.addRequired<LoopInfoWrapperPass>();<br>
            +    }<br>
            +    bool runOnFunction(Function &F) override;<br>
            +    void print(raw_ostream &OS, const Module * =
            nullptr) const override;<br>
            +    void releaseMemory() override {<br>
            +      MustExec.clear();<br>
            +      Ordering.clear();<br>
            +    }<br>
            +  };<br>
            +}<br>
            +<br>
            +char MustExecutePrinter::ID = 0;<br>
            +INITIALIZE_PASS_BEGIN(MustExecutePrinter,
            "print-mustexecute",<br>
            +                      "Instructions which execute on loop
            entry", false, true)<br>
            +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)<br>
            +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)<br>
            +INITIALIZE_PASS_END(MustExecutePrinter,
            "print-mustexecute",<br>
            +                    "Instructions which execute on loop
            entry", false, true)<br>
            +<br>
            +FunctionPass *llvm::createMustExecutePrinter() {<br>
            +  return new MustExecutePrinter();<br>
            +}<br>
            +<br>
            +bool isMustExecuteIn(Instruction &I, Loop *L,
            DominatorTree *DT) {<br>
            +  // TODO: move loop specific code to analysis<br>
            +  //LoopSafetyInfo LSI;<br>
            +  //computeLoopSafetyInfo(&LSI, L);<br>
            +  //return isGuaranteedToExecute(I, DT, L, &LSI);<br>
            +  return isGuaranteedToExecuteForEveryIteration(&I, L);<br>
            +}<br>
            +<br>
            +bool MustExecutePrinter::runOnFunction(Function &F) {<br>
            +  auto &LI =
            getAnalysis<LoopInfoWrapperPass>().getLoopInfo();<br>
            +  auto &DT =
            getAnalysis<DominatorTreeWrapperPass>().getDomTree();<br>
            +  for (auto &I: instructions(F)) {<br>
            +    Loop *L = LI.getLoopFor(I.getParent());<br>
            +    while (L) {<br>
            +      if (isMustExecuteIn(I, L, &DT)) {<br>
            +        if (!MustExec.count(&I))<br>
            +          Ordering.push_back(&I);<br>
            +        MustExec[&I].push_back(L);<br>
            +      }<br>
            +      L = L->getParentLoop();<br>
            +    };<br>
            +  }<br>
            +  return false;<br>
            +}<br>
            +<br>
            +void MustExecutePrinter::print(raw_ostream &OS, const
            Module *M) const {<br>
            +  OS << "The following are guaranteed to execute (for
            the respective loops):\n";<br>
            +  for (Value *V: Ordering) {<br>
            +    V->printAsOperand(OS);<br>
            +    auto NumLoops = MustExec.lookup(V).size();<br>
            +    if (NumLoops > 1)<br>
            +      OS << "\t(mustexec in " << NumLoops
            << " loops: ";<br>
            +    else<br>
            +      OS << "\t(mustexec in: ";<br>
            +<br>
            +    bool first = true;<br>
            +    for (const Loop *L : MustExec.lookup(V)) {<br>
            +      if (!first)<br>
            +        OS << ", ";<br>
            +      first = false;<br>
            +      OS << L->getHeader()->getName();<br>
            +    }<br>
            +    OS << ")\n";<br>
            +  }<br>
            +  OS << "\n";<br>
            +}<br>
            <br>
            Added: llvm/trunk/test/Analysis/MustExecute/loop-header.ll<br>
            URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/MustExecute/loop-header.ll?rev=328004&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/MustExecute/loop-header.ll?rev=328004&view=auto</a><br>
==============================================================================<br>
            --- llvm/trunk/test/Analysis/MustExecute/loop-header.ll
            (added)<br>
            +++ llvm/trunk/test/Analysis/MustExecute/loop-header.ll Tue
            Mar 20 10:09:21 2018<br>
            @@ -0,0 +1,80 @@<br>
            +; RUN: opt -analyze -print-mustexecute %s<br>
            +<br>
            +; CHECK: Printing analysis 'Instructions which execute on
            loop entry' for function 'header_with_icf':<br>
            +; CHECK: The following are guaranteed to execute (for the
            respective loops):<br>
            +; CHECK:   %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop
            ]    (mustexec in: loop)<br>
            +; CHECK:   %v = load i32, i32* %p      (mustexec in: loop)<br>
            +; CHECK:   call void @maythrow_and_use(i32 %v) (mustexec
            in: loop)<br>
            +; CHECK-NOT: add<br>
            +define i1 @header_with_icf(i32* noalias %p, i32 %high) {<br>
            +entry:<br>
            +  br label %loop<br>
            +<br>
            +loop:<br>
            +  %iv = phi i32 [0, %entry], [%iv.next, %loop]<br>
            +  %v = load i32, i32* %p<br>
            +  call void @maythrow_and_use(i32 %v)<br>
            +  %iv.next = add nsw nuw i32 %iv, 1<br>
            +  %exit.test = icmp slt i32 %iv, %high<br>
            +  br i1 %exit.test, label %exit, label %loop<br>
            +<br>
            +exit:<br>
            +  ret i1 false<br>
            +}<br>
            +<br>
            +; CHECK: Printing analysis 'Instructions which execute on
            loop entry' for function 'test':<br>
            +; CHECK: The following are guaranteed to execute (for the
            respective loops):<br>
            +; CHECK:   %iv = phi i32 [ 0, %entry ], [ %iv.next, %next
            ]    (mustexec in: loop)<br>
            +; CHECK:   %v = load i32, i32* %p      (mustexec in: loop)<br>
            +; CHECK:   br label %next      (mustexec in: loop)<br>
            +define i1 @test(i32* noalias %p, i32 %high) {<br>
            +entry:<br>
            +  br label %loop<br>
            +<br>
            +loop:<br>
            +  %iv = phi i32 [0, %entry], [%iv.next, %next]<br>
            +  %v = load i32, i32* %p<br>
            +  br label %next<br>
            +next:<br>
            +  call void @maythrow_and_use(i32 %v)<br>
            +  %iv.next = add nsw nuw i32 %iv, 1<br>
            +  %exit.test = icmp slt i32 %iv, %high<br>
            +  br i1 %exit.test, label %exit, label %loop<br>
            +<br>
            +exit:<br>
            +  ret i1 false<br>
            +}<br>
            +<br>
            +; CHECK: Printing analysis 'Instructions which execute on
            loop entry' for function 'nested':<br>
            +; CHECK: The following are guaranteed to execute (for the
            respective loops):<br>
            +; CHECK:   %iv = phi i32 [ 0, %entry ], [ %iv.next, %next
            ]    (mustexec in: loop)<br>
            +; CHECK:   br label %inner_loop        (mustexec in: loop)<br>
            +; FIXME: These three are also must execute for the outer
            loop.<br>
            +; CHECK:   %v = load i32, i32* %p      (mustexec in:
            inner_loop)<br>
            +; CHECK:   %inner.test = icmp eq i32 %v, 0     (mustexec
            in: inner_loop)<br>
            +; CHECK:   br i1 %inner.test, label %inner_loop, label
            %next   (mustexec in: inner_loop)<br>
            +define i1 @nested(i32* noalias %p, i32 %high) {<br>
            +entry:<br>
            +  br label %loop<br>
            +<br>
            +loop:<br>
            +  %iv = phi i32 [0, %entry], [%iv.next, %next]<br>
            +  br label %inner_loop<br>
            +<br>
            +inner_loop:<br>
            +  %v = load i32, i32* %p<br>
            +  %inner.test = icmp eq i32 %v, 0<br>
            +  br i1 %inner.test, label %inner_loop, label %next<br>
            +<br>
            +next:<br>
            +  call void @maythrow_and_use(i32 %v)<br>
            +  %iv.next = add nsw nuw i32 %iv, 1<br>
            +  %exit.test = icmp slt i32 %iv, %high<br>
            +  br i1 %exit.test, label %exit, label %loop<br>
            +<br>
            +exit:<br>
            +  ret i1 false<br>
            +}<br>
            +<br>
            +<br>
            +declare void @maythrow_and_use(i32)<br>
            <br>
            <br>
            _______________________________________________<br>
            llvm-commits mailing list<br>
            <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
            <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
          </blockquote>
        </div>
      </div>
    </blockquote>
    <br>
  </div></blockquote></div>