<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>I'll have to look at the compiler errors to see what's used.  I
      hadn't intended to leave any of the required functionality in
      Transforms and I'm confused as to what I might have missed.  I'm
      hoping it's something minor.<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 03/29/2018 10:24 AM, David Blaikie
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAENS6Eu-aY+L8T1_S84qx0C29Buqx6rqz=721OQmP2SPhXW_JA@mail.gmail.com">
      <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"
            moz-do-not-send="true">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" moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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"
                      moz-do-not-send="true">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" moz-do-not-send="true">llvm-commits@lists.llvm.org</a><br>
                    <a
                      href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits"
                      rel="noreferrer" target="_blank"
                      moz-do-not-send="true">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
                  </blockquote>
                </div>
              </div>
            </blockquote>
            <br>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>