<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Yep, turned out to be a terminology problem.  The limitation of
      not jump threading over headers is a known one.  Thanks for the
      clarification.</p>
    <p>Philip<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 01/08/2018 08:29 AM, Brian M. Rzycki
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAPGb_Rt4K1sn4hY0UnxO=-zm--0Wh8abF5EuE-yYCHvPO=yBzw@mail.gmail.com">
      <div dir="ltr"><span style="font-size:12.8px">Hello Philip,</span>
        <div style="font-size:12.8px"><br>
        </div>
        <div style="font-size:12.8px">The current implementation of
          LLVM's JumpThreading pass actively discards any opportunities
          that span into, or out of, a loop. You can see the check for
          this at the very top of JumpThreadingPass::ProcessT<wbr>hreadableEdges().
          This is what I meant by loop boundary threading. :)</div>
        <div style="font-size:12.8px"><br>
        </div>
        <div style="font-size:12.8px">At a high-level the LLVM JT pass
          can only optimize a very specific three block BB opportunity
          with the shape of [Prev]->[BB]->[Succ]. The rest of the
          pass spends all its time attempting to produce and detect as
          many of these block shapes as it can.  This is quite different
          from GCC's JT pass that has a clear analysis of potential
          threadable edge paths and then the actual threading being
          done. The GCC pass also allows for several blocks on its
          threaded chain.</div>
        <div style="font-size:12.8px"><br>
        </div>
        <div style="font-size:12.8px">There are quite a few real-world
          examples where threading into/out of a loop is beneficial. One
          prominent pattern is text file parsers. These parsers usually
          have nested case/switch blocks inside a while(EOF) loop and
          contain token detection state. Here is one such test that
          illustrates this pattern:</div>
        <div style="font-size:12.8px"><br>
        </div>
        <div style="font-size:12.8px"><a
href="https://github.com/gcc-mirror/gcc/blob/master/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c"
            target="_blank" moz-do-not-send="true">https://github.com/gcc-mirror/<wbr>gcc/blob/master/gcc/testsuite/<wbr>gcc.dg/tree-ssa/ssa-dom-<wbr>thread-8.c</a><br>
        </div>
        <div style="font-size:12.8px"><br>
        </div>
        <div style="font-size:12.8px">When I worked with Sebastian in
          2015 to extend GCC's JT parser we also detected this pattern
          within GCC itself and saw a modest (couple of percentage
          points) performance boost to the compiler run-time.</div>
        <div style="font-size:12.8px"><br>
        </div>
        <div style="font-size:12.8px">Hope that helps,</div>
        <div style="font-size:12.8px">-Brian</div>
      </div>
      <div class="gmail_extra"><br>
        <div class="gmail_quote">On Fri, Jan 5, 2018 at 1:00 PM, Philip
          Reames <span dir="ltr"><<a
              href="mailto:listmail@philipreames.com" target="_blank"
              moz-do-not-send="true">listmail@philipreames.com</a>></span>
          wrote:<br>
          <blockquote class="gmail_quote" style="margin:0 0 0
            .8ex;border-left:1px #ccc solid;padding-left:1ex">Out of
            curiosity, what is "loop boundary threading"?  I'm
            unfamiliar with this and can find zero hits on google.  :)<br>
            <br>
            Philip<br>
            <br>
            On 01/04/2018 01:57 PM, Brian M. Rzycki via llvm-commits
            wrote:<br>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              Author: brzycki<br>
              Date: Thu Jan  4 13:57:32 2018<br>
              New Revision: 321825<br>
              <br>
              URL: <a
                href="http://llvm.org/viewvc/llvm-project?rev=321825&view=rev"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=321825&view=rev</a><br>
              Log:<br>
              [JumpThreading] Preservation of DT and LVI across the pass<br>
              <br>
              Summary:<br>
              See D37528 for a previous (non-deferred) version of this<br>
              patch and its description.<br>
              <br>
              Preserves dominance in a deferred manner using a new class<br>
              DeferredDominance. This reduces the performance impact of<br>
              updating the DominatorTree at every edge insertion and<br>
              deletion. A user may call DDT->flush() within
              JumpThreading<br>
              for an up-to-date DT. This patch currently has one flush()<br>
              at the end of runImpl() to ensure DT is preserved across<br>
              the pass.<br>
              <br>
              LVI is also preserved to help subsequent passes such as<br>
              CorrelatedValuePropagation. LVI is simpler to maintain and<br>
              is done immediately (not deferred). The code to perfom the<br>
              preversation was minimally altered and was simply marked<br>
              as preserved for the PassManager to be informed.<br>
              <br>
              This extends the analysis available to JumpThreading for<br>
              future enhancements. One example is loop boundary
              threading.<br>
              <br>
              Reviewers: dberlin, kuhar, sebpop<br>
              <br>
              Reviewed By: kuhar, sebpop<br>
              <br>
              Subscribers: hiraditya, llvm-commits<br>
              <br>
              Differential Revision: <a
                href="https://reviews.llvm.org/D40146" rel="noreferrer"
                target="_blank" moz-do-not-send="true">https://reviews.llvm.org/D4014<wbr>6</a><br>
              <br>
              Added:<br>
                   llvm/trunk/test/Transforms/Ju<wbr>mpThreading/ddt-crash.ll<br>
                   llvm/trunk/test/Transforms/Ju<wbr>mpThreading/lvi-tristate.ll<br>
              Modified:<br>
                   llvm/trunk/include/llvm/IR/Do<wbr>minators.h<br>
                   llvm/trunk/include/llvm/Trans<wbr>forms/Scalar/JumpThreading.h<br>
                   llvm/trunk/include/llvm/Trans<wbr>forms/Utils/BasicBlockUtils.h<br>
                   llvm/trunk/include/llvm/Trans<wbr>forms/Utils/Local.h<br>
                   llvm/trunk/lib/IR/Dominators.<wbr>cpp<br>
                   llvm/trunk/lib/Transforms/Sca<wbr>lar/CorrelatedValuePropagation<wbr>.cpp<br>
                   llvm/trunk/lib/Transforms/Sca<wbr>lar/JumpThreading.cpp<br>
                   llvm/trunk/lib/Transforms/Uti<wbr>ls/BasicBlockUtils.cpp<br>
                   llvm/trunk/lib/Transforms/Uti<wbr>ls/Local.cpp<br>
                   llvm/trunk/test/Analysis/Lazy<wbr>ValueAnalysis/lvi-after-jumpth<wbr>reading.ll<br>
              <br>
              Modified: llvm/trunk/include/llvm/IR/Dom<wbr>inators.h<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Dominators.h?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>IR/Dominators.h?rev=321825&r1=<wbr>321824&r2=321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/include/llvm/IR/Dom<wbr>inators.h
              (original)<br>
              +++ llvm/trunk/include/llvm/IR/Dom<wbr>inators.h Thu Jan 
              4 13:57:32 2018<br>
              @@ -290,6 +290,90 @@ public:<br>
                  void print(raw_ostream &OS, const Module *M =
              nullptr) const override;<br>
                };<br>
                +//===------------------------<wbr>-------------<br>
              +/// \brief Class to defer updates to a DominatorTree.<br>
              +///<br>
              +/// Definition: Applying updates to every edge insertion
              and deletion is<br>
              +/// expensive and not necessary. When one needs the
              DominatorTree for analysis<br>
              +/// they can request a flush() to perform a larger batch
              update. This has the<br>
              +/// advantage of the DominatorTree inspecting the set of
              updates to find<br>
              +/// duplicates or unnecessary subtree updates.<br>
              +///<br>
              +/// The scope of DeferredDominance operates at a Function
              level.<br>
              +///<br>
              +/// It is not necessary for the user to scrub the updates
              for duplicates or<br>
              +/// updates that point to the same block (Delete, BB_A,
              BB_A). Performance<br>
              +/// can be gained if the caller attempts to batch updates
              before submitting<br>
              +/// to applyUpdates(ArrayRef) in cases where duplicate
              edge requests will<br>
              +/// occur.<br>
              +///<br>
              +/// It is required for the state of the LLVM IR to be
              applied *before*<br>
              +/// submitting updates. The update routines must analyze
              the current state<br>
              +/// between a pair of (From, To) basic blocks to
              determine if the update<br>
              +/// needs to be queued.<br>
              +/// Example (good):<br>
              +///     TerminatorInstructionBB->remo<wbr>veFromParent();<br>
              +///     DDT->deleteEdge(BB, Successor);<br>
              +/// Example (bad):<br>
              +///     DDT->deleteEdge(BB, Successor);<br>
              +///     TerminatorInstructionBB->remo<wbr>veFromParent();<br>
              +class DeferredDominance {<br>
              +public:<br>
              +  DeferredDominance(DominatorTre<wbr>e &DT_) :
              DT(DT_) {}<br>
              +<br>
              +  /// \brief Queues multiple updates and discards
              duplicates.<br>
              +  void applyUpdates(ArrayRef<Dominato<wbr>rTree::UpdateType>
              Updates);<br>
              +<br>
              +  /// \brief Helper method for a single edge insertion.
              It's almost always<br>
              +  /// better to batch updates and call applyUpdates to
              quickly remove duplicate<br>
              +  /// edges. This is best used when there is only a
              single insertion needed to<br>
              +  /// update Dominators.<br>
              +  void insertEdge(BasicBlock *From, BasicBlock *To);<br>
              +<br>
              +  /// \brief Helper method for a single edge deletion.
              It's almost always better<br>
              +  /// to batch updates and call applyUpdates to quickly
              remove duplicate edges.<br>
              +  /// This is best used when there is only a single
              deletion needed to update<br>
              +  /// Dominators.<br>
              +  void deleteEdge(BasicBlock *From, BasicBlock *To);<br>
              +<br>
              +  /// \brief Delays the deletion of a basic block until a
              flush() event.<br>
              +  void deleteBB(BasicBlock *DelBB);<br>
              +<br>
              +  /// \brief Returns true if DelBB is awaiting deletion
              at a flush() event.<br>
              +  bool pendingDeletedBB(BasicBlock *DelBB);<br>
              +<br>
              +  /// \brief Flushes all pending updates and block
              deletions. Returns a<br>
              +  /// correct DominatorTree reference to be used by the
              caller for analysis.<br>
              +  DominatorTree &flush();<br>
              +<br>
              +  /// \brief Drops all internal state and forces a (slow)
              recalculation of the<br>
              +  /// DominatorTree based on the current state of the
              LLVM IR in F. This should<br>
              +  /// only be used in corner cases such as the Entry
              block of F being deleted.<br>
              +  void recalculate(Function &F);<br>
              +<br>
              +  /// \brief Debug method to help view the state of
              pending updates.<br>
              +  LLVM_DUMP_METHOD void dump() const;<br>
              +<br>
              +private:<br>
              +  DominatorTree &DT;<br>
              +  SmallVector<DominatorTree::Upd<wbr>ateType, 16>
              PendUpdates;<br>
              +  SmallPtrSet<BasicBlock *, 8> DeletedBBs;<br>
              +<br>
              +  /// Apply an update (Kind, From, To) to the internal
              queued updates. The<br>
              +  /// update is only added when determined to be
              necessary. Checks for<br>
              +  /// self-domination, unnecessary updates, duplicate
              requests, and balanced<br>
              +  /// pairs of requests are all performed. Returns true
              if the update is<br>
              +  /// queued and false if it is discarded.<br>
              +  bool applyUpdate(DominatorTree::Upd<wbr>ateKind Kind,
              BasicBlock *From,<br>
              +                   BasicBlock *To);<br>
              +<br>
              +  /// Performs all pending basic block deletions. We have
              to defer the deletion<br>
              +  /// of these blocks until after the DominatorTree
              updates are applied. The<br>
              +  /// internal workings of the DominatorTree code expect
              every update's From<br>
              +  /// and To blocks to exist and to be a member of the
              same Function.<br>
              +  bool flushDelBB();<br>
              +};<br>
              +<br>
                } // end namespace llvm<br>
                  #endif // LLVM_IR_DOMINATORS_H<br>
              <br>
              Modified: llvm/trunk/include/llvm/Transf<wbr>orms/Scalar/JumpThreading.h<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>Transforms/Scalar/JumpThreadin<wbr>g.h?rev=321825&r1=321824&r2=<wbr>321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/include/llvm/Transf<wbr>orms/Scalar/JumpThreading.h
              (original)<br>
              +++ llvm/trunk/include/llvm/Transf<wbr>orms/Scalar/JumpThreading.h
              Thu Jan  4 13:57:32 2018<br>
              @@ -34,6 +34,7 @@ class BinaryOperator;<br>
                class BranchInst;<br>
                class CmpInst;<br>
                class Constant;<br>
              +class DeferredDominance;<br>
                class Function;<br>
                class Instruction;<br>
                class IntrinsicInst;<br>
              @@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInf<br>
                  TargetLibraryInfo *TLI;<br>
                  LazyValueInfo *LVI;<br>
                  AliasAnalysis *AA;<br>
              +  DeferredDominance *DDT;<br>
                  std::unique_ptr<BlockFrequency<wbr>Info> BFI;<br>
                  std::unique_ptr<BranchProbabil<wbr>ityInfo> BPI;<br>
                  bool HasProfileData = false;<br>
              @@ -107,8 +109,8 @@ public:<br>
                    // Glue for old PM.<br>
                  bool runImpl(Function &F, TargetLibraryInfo *TLI_,
              LazyValueInfo *LVI_,<br>
              -               AliasAnalysis *AA_, bool HasProfileData_,<br>
              -               std::unique_ptr<BlockFrequenc<wbr>yInfo>
              BFI_,<br>
              +               AliasAnalysis *AA_, DeferredDominance
              *DDT_,<br>
              +               bool HasProfileData_,
              std::unique_ptr<BlockFrequency<wbr>Info> BFI_,<br>
                               std::unique_ptr<BranchProbabi<wbr>lityInfo>
              BPI_);<br>
                    PreservedAnalyses run(Function &F,
              FunctionAnalysisManager &AM);<br>
              <br>
              Modified: llvm/trunk/include/llvm/Transf<wbr>orms/Utils/BasicBlockUtils.h<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>Transforms/Utils/BasicBlockUti<wbr>ls.h?rev=321825&r1=321824&r2=<wbr>321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/include/llvm/Transf<wbr>orms/Utils/BasicBlockUtils.h
              (original)<br>
              +++ llvm/trunk/include/llvm/Transf<wbr>orms/Utils/BasicBlockUtils.h
              Thu Jan  4 13:57:32 2018<br>
              @@ -27,6 +27,7 @@ namespace llvm {<br>
                  class BlockFrequencyInfo;<br>
                class BranchProbabilityInfo;<br>
              +class DeferredDominance;<br>
                class DominatorTree;<br>
                class Function;<br>
                class Instruction;<br>
              @@ -38,7 +39,7 @@ class TargetLibraryInfo;<br>
                class Value;<br>
                  /// Delete the specified block, which must have no
              predecessors.<br>
              -void DeleteDeadBlock(BasicBlock *BB);<br>
              +void DeleteDeadBlock(BasicBlock *BB, DeferredDominance
              *DDT = nullptr);<br>
                  /// We know that BB has one predecessor. If there are
              any single-entry PHI nodes<br>
                /// in it, fold them away. This handles the case when
              all entries to the PHI<br>
              <br>
              Modified: llvm/trunk/include/llvm/Transf<wbr>orms/Utils/Local.h<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>Transforms/Utils/Local.h?rev=<wbr>321825&r1=321824&r2=321825&<wbr>view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/include/llvm/Transf<wbr>orms/Utils/Local.h
              (original)<br>
              +++ llvm/trunk/include/llvm/Transf<wbr>orms/Utils/Local.h
              Thu Jan  4 13:57:32 2018<br>
              @@ -117,7 +117,8 @@ struct SimplifyCFGOptions {<br>
                /// conditions and indirectbr addresses this might make
              dead if<br>
                /// DeleteDeadConditions is true.<br>
                bool ConstantFoldTerminator(BasicBl<wbr>ock *BB, bool
              DeleteDeadConditions = false,<br>
              -                            const TargetLibraryInfo *TLI
              = nullptr);<br>
              +                            const TargetLibraryInfo *TLI
              = nullptr,<br>
              +                            DeferredDominance *DDT =
              nullptr);<br>
                  //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
                //  Local dead code elimination.<br>
              @@ -171,18 +172,21 @@ bool SimplifyInstructionsInBlock(Ba<wbr>sicBl<br>
                ///<br>
                /// .. and delete the predecessor corresponding to the
              '1', this will attempt to<br>
                /// recursively fold the 'and' to 0.<br>
              -void RemovePredecessorAndSimplify(B<wbr>asicBlock *BB,
              BasicBlock *Pred);<br>
              +void RemovePredecessorAndSimplify(B<wbr>asicBlock *BB,
              BasicBlock *Pred,<br>
              +                                  DeferredDominance *DDT
              = nullptr);<br>
                  /// BB is a block with one predecessor and its
              predecessor is known to have one<br>
                /// successor (BB!). Eliminate the edge between them,
              moving the instructions in<br>
                /// the predecessor into BB. This deletes the
              predecessor block.<br>
              -void MergeBasicBlockIntoOnlyPred(Ba<wbr>sicBlock *BB,
              DominatorTree *DT = nullptr);<br>
              +void MergeBasicBlockIntoOnlyPred(Ba<wbr>sicBlock *BB,
              DominatorTree *DT = nullptr,<br>
              +                                 DeferredDominance *DDT =
              nullptr);<br>
                  /// BB is known to contain an unconditional branch,
              and contains no instructions<br>
                /// other than PHI nodes, potential debug intrinsics and
              the branch. If<br>
                /// possible, eliminate BB by rewriting all the
              predecessors to branch to the<br>
                /// successor block and return true. If we can't
              transform, return false.<br>
              -bool TryToSimplifyUncondBranchFromE<wbr>mptyBlock(BasicBlock
              *BB);<br>
              +bool TryToSimplifyUncondBranchFromE<wbr>mptyBlock(BasicBlock
              *BB,<br>
              +                                           
               DeferredDominance *DDT = nullptr);<br>
                  /// Check for and eliminate duplicate PHI nodes in
              this block. This doesn't try<br>
                /// to be clever about PHI nodes which differ only in
              the order of the incoming<br>
              @@ -382,7 +386,8 @@ unsigned
              removeAllNonTerminatorAndEHPad<wbr>I<br>
                /// Insert an unreachable instruction before the
              specified<br>
                /// instruction, making it and the rest of the code in
              the block dead.<br>
                unsigned changeToUnreachable(Instructio<wbr>n *I, bool
              UseLLVMTrap,<br>
              -                             bool PreserveLCSSA = false);<br>
              +                             bool PreserveLCSSA = false,<br>
              +                             DeferredDominance *DDT =
              nullptr);<br>
                  /// Convert the CallInst to InvokeInst with the
              specified unwind edge basic<br>
                /// block.  This also splits the basic block where CI is
              located, because<br>
              @@ -397,12 +402,13 @@ BasicBlock
              *changeToInvokeAndSplitBasicB<br>
                ///<br>
                /// \param BB  Block whose terminator will be replaced. 
              Its terminator must<br>
                ///            have an unwind successor.<br>
              -void removeUnwindEdge(BasicBlock *BB);<br>
              +void removeUnwindEdge(BasicBlock *BB, DeferredDominance
              *DDT = nullptr);<br>
                  /// Remove all blocks that can not be reached from the
              function's entry.<br>
                ///<br>
                /// Returns true if any basic block was removed.<br>
              -bool removeUnreachableBlocks(Functi<wbr>on &F,
              LazyValueInfo *LVI = nullptr);<br>
              +bool removeUnreachableBlocks(Functi<wbr>on &F,
              LazyValueInfo *LVI = nullptr,<br>
              +                             DeferredDominance *DDT =
              nullptr);<br>
                  /// Combine the metadata of two instructions so that K
              can replace J<br>
                ///<br>
              <br>
              Modified: llvm/trunk/lib/IR/Dominators.c<wbr>pp<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Dominators.cpp?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/Domina<wbr>tors.cpp?rev=321825&r1=321824&<wbr>r2=321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/lib/IR/Dominators.c<wbr>pp (original)<br>
              +++ llvm/trunk/lib/IR/Dominators.c<wbr>pp Thu Jan  4
              13:57:32 2018<br>
              @@ -18,6 +18,7 @@<br>
                #include "llvm/ADT/DepthFirstIterator.h<wbr>"<br>
                #include "llvm/ADT/SmallPtrSet.h"<br>
                #include "llvm/IR/CFG.h"<br>
              +#include "llvm/IR/Constants.h"<br>
                #include "llvm/IR/Instructions.h"<br>
                #include "llvm/IR/PassManager.h"<br>
                #include "llvm/Support/CommandLine.h"<br>
              @@ -389,3 +390,190 @@ void DominatorTreeWrapperPass::prin<wbr>t(raw<br>
                  DT.print(OS);<br>
                }<br>
                +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
              +//  DeferredDominance Implementation<br>
              +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
              +//<br>
              +// The implementation details of the DeferredDominance
              class which allows<br>
              +// one to queue updates to a DominatorTree.<br>
              +//<br>
              +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
              +<br>
              +/// \brief Queues multiple updates and discards
              duplicates.<br>
              +void DeferredDominance::applyUpdate<wbr>s(<br>
              +    ArrayRef<DominatorTree::Update<wbr>Type>
              Updates) {<br>
              +  SmallVector<DominatorTree::Upd<wbr>ateType, 8>
              Seen;<br>
              +  for (auto U : Updates)<br>
              +    // Avoid duplicates to applyUpdate() to save on
              analysis.<br>
              +    if (std::none_of(Seen.begin(), Seen.end(),<br>
              +                     [U](DominatorTree::UpdateType S) {
              return S == U; })) {<br>
              +      Seen.push_back(U);<br>
              +      applyUpdate(U.getKind(), U.getFrom(), U.getTo());<br>
              +    }<br>
              +}<br>
              +<br>
              +/// \brief Helper method for a single edge insertion.
              It's almost always better<br>
              +/// to batch updates and call applyUpdates to quickly
              remove duplicate edges.<br>
              +/// This is best used when there is only a single
              insertion needed to update<br>
              +/// Dominators.<br>
              +void DeferredDominance::insertEdge(<wbr>BasicBlock *From,
              BasicBlock *To) {<br>
              +  applyUpdate(DominatorTree::Ins<wbr>ert, From, To);<br>
              +}<br>
              +<br>
              +/// \brief Helper method for a single edge deletion. It's
              almost always better<br>
              +/// to batch updates and call applyUpdates to quickly
              remove duplicate edges.<br>
              +/// This is best used when there is only a single
              deletion needed to update<br>
              +/// Dominators.<br>
              +void DeferredDominance::deleteEdge(<wbr>BasicBlock *From,
              BasicBlock *To) {<br>
              +  applyUpdate(DominatorTree::Del<wbr>ete, From, To);<br>
              +}<br>
              +<br>
              +/// \brief Delays the deletion of a basic block until a
              flush() event.<br>
              +void DeferredDominance::deleteBB(Ba<wbr>sicBlock *DelBB)
              {<br>
              +  assert(DelBB && "Invalid push_back of nullptr
              DelBB.");<br>
              +  assert(pred_empty(DelBB) && "DelBB has one or
              more predecessors.");<br>
              +  // DelBB is unreachable and all its instructions are
              dead.<br>
              +  while (!DelBB->empty()) {<br>
              +    Instruction &I = DelBB->back();<br>
              +    // Replace used instructions with an arbitrary value
              (undef).<br>
              +    if (!I.use_empty())<br>
              +      I.replaceAllUsesWith(llvm::Und<wbr>efValue::get(I.getType()));<br>
              +    DelBB->getInstList().pop_back(<wbr>);<br>
              +  }<br>
              +  // Make sure DelBB has a valid terminator instruction.
              As long as DelBB is a<br>
              +  // Child of Function F it must contain valid IR.<br>
              +  new UnreachableInst(DelBB->getCont<wbr>ext(),
              DelBB);<br>
              +  DeletedBBs.insert(DelBB);<br>
              +}<br>
              +<br>
              +/// \brief Returns true if DelBB is awaiting deletion at
              a flush() event.<br>
              +bool DeferredDominance::pendingDele<wbr>tedBB(BasicBlock
              *DelBB) {<br>
              +  if (DeletedBBs.empty())<br>
              +    return false;<br>
              +  return DeletedBBs.count(DelBB) != 0;<br>
              +}<br>
              +<br>
              +/// \brief Flushes all pending updates and block
              deletions. Returns a<br>
              +/// correct DominatorTree reference to be used by the
              caller for analysis.<br>
              +DominatorTree &DeferredDominance::flush() {<br>
              +  // Updates to DT must happen before blocks are deleted
              below. Otherwise the<br>
              +  // DT traversal will encounter badref blocks and
              assert.<br>
              +  if (!PendUpdates.empty()) {<br>
              +    DT.applyUpdates(PendUpdates);<br>
              +    PendUpdates.clear();<br>
              +  }<br>
              +  flushDelBB();<br>
              +  return DT;<br>
              +}<br>
              +<br>
              +/// \brief Drops all internal state and forces a (slow)
              recalculation of the<br>
              +/// DominatorTree based on the current state of the LLVM
              IR in F. This should<br>
              +/// only be used in corner cases such as the Entry block
              of F being deleted.<br>
              +void DeferredDominance::recalculate<wbr>(Function &F)
              {<br>
              +  // flushDelBB must be flushed before the recalculation.
              The state of the IR<br>
              +  // must be consistent before the DT traversal algorithm
              determines the<br>
              +  // actual DT.<br>
              +  if (flushDelBB() || !PendUpdates.empty()) {<br>
              +    DT.recalculate(F);<br>
              +    PendUpdates.clear();<br>
              +  }<br>
              +}<br>
              +<br>
              +/// \brief Debug method to help view the state of pending
              updates.<br>
              +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)<br>
              +LLVM_DUMP_METHOD void DeferredDominance::dump() const {<br>
              +  raw_ostream &OS = llvm::dbgs();<br>
              +  OS << "PendUpdates:\n";<br>
              +  int I = 0;<br>
              +  for (auto U : PendUpdates) {<br>
              +    OS << "  " << I << " : ";<br>
              +    ++I;<br>
              +    if (U.getKind() == DominatorTree::Insert)<br>
              +      OS << "Insert, ";<br>
              +    else<br>
              +      OS << "Delete, ";<br>
              +    BasicBlock *From = U.getFrom();<br>
              +    if (From) {<br>
              +      auto S = From->getName();<br>
              +      if (!From->hasName())<br>
              +        S = "(no name)";<br>
              +      OS << S << "(" << From <<
              "), ";<br>
              +    } else {<br>
              +      OS << "(badref), ";<br>
              +    }<br>
              +    BasicBlock *To = U.getTo();<br>
              +    if (To) {<br>
              +      auto S = To->getName();<br>
              +      if (!To->hasName())<br>
              +        S = "(no_name)";<br>
              +      OS << S << "(" << To <<
              ")\n";<br>
              +    } else {<br>
              +      OS << "(badref)\n";<br>
              +    }<br>
              +  }<br>
              +  OS << "DeletedBBs:\n";<br>
              +  I = 0;<br>
              +  for (auto BB : DeletedBBs) {<br>
              +    OS << "  " << I << " : ";<br>
              +    ++I;<br>
              +    if (BB->hasName())<br>
              +      OS << BB->getName() << "(";<br>
              +    else<br>
              +      OS << "(no_name)(";<br>
              +    OS << BB << ")\n";<br>
              +  }<br>
              +}<br>
              +#endif<br>
              +<br>
              +/// Apply an update (Kind, From, To) to the internal
              queued updates. The<br>
              +/// update is only added when determined to be necessary.
              Checks for<br>
              +/// self-domination, unnecessary updates, duplicate
              requests, and balanced<br>
              +/// pairs of requests are all performed. Returns true if
              the update is<br>
              +/// queued and false if it is discarded.<br>
              +bool DeferredDominance::applyUpdate<wbr>(DominatorTree::UpdateKind
              Kind,<br>
              +                                    BasicBlock *From,
              BasicBlock *To) {<br>
              +  if (From == To)<br>
              +    return false; // Cannot dominate self; discard
              update.<br>
              +<br>
              +  // Discard updates by inspecting the current state of
              successors of From.<br>
              +  // Since applyUpdate() must be called *after* the
              Terminator of From is<br>
              +  // altered we can determine if the update is
              unnecessary.<br>
              +  bool HasEdge = std::any_of(succ_begin(From),
              succ_end(From),<br>
              +                             [To](BasicBlock *B) { return
              B == To; });<br>
              +  if (Kind == DominatorTree::Insert && !HasEdge)<br>
              +    return false; // Unnecessary Insert: edge does not
              exist in IR.<br>
              +  if (Kind == DominatorTree::Delete && HasEdge)<br>
              +    return false; // Unnecessary Delete: edge still
              exists in IR.<br>
              +<br>
              +  // Analyze pending updates to determine if the update
              is unnecessary.<br>
              +  DominatorTree::UpdateType Update = {Kind, From, To};<br>
              +  DominatorTree::UpdateType Invert = {Kind !=
              DominatorTree::Insert<br>
              +                                          ?
              DominatorTree::Insert<br>
              +                                          :
              DominatorTree::Delete,<br>
              +                                      From, To};<br>
              +  for (auto I = PendUpdates.begin(), E =
              PendUpdates.end(); I != E; ++I) {<br>
              +    if (Update == *I)<br>
              +      return false; // Discard duplicate updates.<br>
              +    if (Invert == *I) {<br>
              +      // Update and Invert are both valid (equivalent to
              a no-op). Remove<br>
              +      // Invert from PendUpdates and discard the Update.<br>
              +      PendUpdates.erase(I);<br>
              +      return false;<br>
              +    }<br>
              +  }<br>
              +  PendUpdates.push_back(Update); // Save the valid
              update.<br>
              +  return true;<br>
              +}<br>
              +<br>
              +/// Performs all pending basic block deletions. We have
              to defer the deletion<br>
              +/// of these blocks until after the DominatorTree updates
              are applied. The<br>
              +/// internal workings of the DominatorTree code expect
              every update's From<br>
              +/// and To blocks to exist and to be a member of the same
              Function.<br>
              +bool DeferredDominance::flushDelBB(<wbr>) {<br>
              +  if (DeletedBBs.empty())<br>
              +    return false;<br>
              +  for (auto *BB : DeletedBBs)<br>
              +    BB->eraseFromParent();<br>
              +  DeletedBBs.clear();<br>
              +  return true;<br>
              +}<br>
              <br>
              Modified: llvm/trunk/lib/Transforms/Scal<wbr>ar/CorrelatedValuePropagation.<wbr>cpp<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Scalar/CorrelatedValuePropag<wbr>ation.cpp?rev=321825&r1=<wbr>321824&r2=321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/lib/Transforms/Scal<wbr>ar/CorrelatedValuePropagation.<wbr>cpp
              (original)<br>
              +++ llvm/trunk/lib/Transforms/Scal<wbr>ar/CorrelatedValuePropagation.<wbr>cpp
              Thu Jan  4 13:57:32 2018<br>
              @@ -77,6 +77,7 @@ namespace {<br>
                    bool runOnFunction(Function &F) override;<br>
                      void getAnalysisUsage(AnalysisUsage &AU) const
              override {<br>
              +      AU.addRequired<DominatorTreeWr<wbr>apperPass>();<br>
                      AU.addRequired<LazyValueInfoWr<wbr>apperPass>();<br>
                      AU.addPreserved<GlobalsAAWrapp<wbr>erPass>();<br>
                    }<br>
              @@ -88,6 +89,7 @@ char CorrelatedValuePropagation::ID = 0;<br>
                  INITIALIZE_PASS_BEGIN(Correlat<wbr>edValuePropagation,
              "correlated-propagation",<br>
                                "Value Propagation", false, false)<br>
              +INITIALIZE_PASS_DEPENDENCY(Do<wbr>minatorTreeWrapperPass)<br>
                INITIALIZE_PASS_DEPENDENCY(Laz<wbr>yValueInfoWrapperPass)<br>
                INITIALIZE_PASS_END(Correlated<wbr>ValuePropagation,
              "correlated-propagation",<br>
                                "Value Propagation", false, false)<br>
              <br>
              Modified: llvm/trunk/lib/Transforms/Scal<wbr>ar/JumpThreading.cpp<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Scalar/JumpThreading.cpp?<wbr>rev=321825&r1=321824&r2=<wbr>321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/lib/Transforms/Scal<wbr>ar/JumpThreading.cpp
              (original)<br>
              +++ llvm/trunk/lib/Transforms/Scal<wbr>ar/JumpThreading.cpp
              Thu Jan  4 13:57:32 2018<br>
              @@ -131,10 +131,11 @@ namespace {<br>
                    bool runOnFunction(Function &F) override;<br>
                      void getAnalysisUsage(AnalysisUsage &AU) const
              override {<br>
              -      if (PrintLVIAfterJumpThreading)<br>
              -        AU.addRequired<DominatorTreeWr<wbr>apperPass>();<br>
              +      AU.addRequired<DominatorTreeWr<wbr>apperPass>();<br>
              +      AU.addPreserved<DominatorTreeW<wbr>rapperPass>();<br>
                      AU.addRequired<AAResultsWrappe<wbr>rPass>();<br>
                      AU.addRequired<LazyValueInfoWr<wbr>apperPass>();<br>
              +      AU.addPreserved<LazyValueInfoW<wbr>rapperPass>();<br>
                      AU.addPreserved<GlobalsAAWrapp<wbr>erPass>();<br>
                      AU.addRequired<TargetLibraryIn<wbr>foWrapperPass>();<br>
                    }<br>
              @@ -148,6 +149,7 @@ char JumpThreading::ID = 0;<br>
                  INITIALIZE_PASS_BEGIN(JumpThre<wbr>ading,
              "jump-threading",<br>
                                "Jump Threading", false, false)<br>
              +INITIALIZE_PASS_DEPENDENCY(Do<wbr>minatorTreeWrapperPass)<br>
                INITIALIZE_PASS_DEPENDENCY(Laz<wbr>yValueInfoWrapperPass)<br>
                INITIALIZE_PASS_DEPENDENCY(Tar<wbr>getLibraryInfoWrapperPass)<br>
                INITIALIZE_PASS_DEPENDENCY(AAR<wbr>esultsWrapperPass)<br>
              @@ -278,8 +280,12 @@ bool JumpThreading::runOnFunction(F<wbr>uncti<br>
                  if (skipFunction(F))<br>
                    return false;<br>
                  auto TLI = &getAnalysis<TargetLibraryInfo<wbr>WrapperPass>().getTLI();<br>
              +  // Get DT analysis before LVI. When LVI is initialized
              it conditionally adds<br>
              +  // DT if it's available.<br>
              +  auto DT = &getAnalysis<DominatorTreeWrap<wbr>perPass>().getDomTree();<br>
                  auto LVI = &getAnalysis<LazyValueInfoWrap<wbr>perPass>().getLVI();<br>
                  auto AA = &getAnalysis<AAResultsWrapperP<wbr>ass>().getAAResults();<br>
              +  DeferredDominance DDT(*DT);<br>
                  std::unique_ptr<BlockFrequency<wbr>Info> BFI;<br>
                  std::unique_ptr<BranchProbabil<wbr>ityInfo> BPI;<br>
                  bool HasProfileData = F.hasProfileData();<br>
              @@ -289,12 +295,11 @@ bool JumpThreading::runOnFunction(F<wbr>uncti<br>
                    BFI.reset(new BlockFrequencyInfo(F, *BPI, LI));<br>
                  }<br>
                -  bool Changed = Impl.runImpl(F, TLI, LVI, AA,
              HasProfileData, std::move(BFI),<br>
              -                              std::move(BPI));<br>
              +  bool Changed = Impl.runImpl(F, TLI, LVI, AA, &DDT,
              HasProfileData,<br>
              +                              std::move(BFI),
              std::move(BPI));<br>
                  if (PrintLVIAfterJumpThreading) {<br>
                    dbgs() << "LVI for function '" <<
              F.getName() << "':\n";<br>
              -    LVI->printLVI(F, getAnalysis<DominatorTreeWrapp<wbr>erPass>().getDomTree(),<br>
              -                  dbgs());<br>
              +    LVI->printLVI(F, *DT, dbgs());<br>
                  }<br>
                  return Changed;<br>
                }<br>
              @@ -302,8 +307,12 @@ bool JumpThreading::runOnFunction(F<wbr>uncti<br>
                PreservedAnalyses JumpThreadingPass::run(Functio<wbr>n
              &F,<br>
                                                       
               FunctionAnalysisManager &AM) {<br>
                  auto &TLI = AM.getResult<TargetLibraryAnal<wbr>ysis>(F);<br>
              +  // Get DT analysis before LVI. When LVI is initialized
              it conditionally adds<br>
              +  // DT if it's available.<br>
              +  auto &DT = AM.getResult<DominatorTreeAnal<wbr>ysis>(F);<br>
                  auto &LVI = AM.getResult<LazyValueAnalysis<wbr>>(F);<br>
                  auto &AA = AM.getResult<AAManager>(F);<br>
              +  DeferredDominance DDT(DT);<br>
                    std::unique_ptr<BlockFrequency<wbr>Info> BFI;<br>
                  std::unique_ptr<BranchProbabil<wbr>ityInfo> BPI;<br>
              @@ -313,25 +322,28 @@ PreservedAnalyses
              JumpThreadingPass::run<br>
                    BFI.reset(new BlockFrequencyInfo(F, *BPI, LI));<br>
                  }<br>
                -  bool Changed = runImpl(F, &TLI, &LVI,
              &AA, HasProfileData, std::move(BFI),<br>
              -                         std::move(BPI));<br>
              +  bool Changed = runImpl(F, &TLI, &LVI, &AA,
              &DDT, HasProfileData,<br>
              +                         std::move(BFI), std::move(BPI));<br>
                    if (!Changed)<br>
                    return PreservedAnalyses::all();<br>
                  PreservedAnalyses PA;<br>
                  PA.preserve<GlobalsAA>();<br>
              +  PA.preserve<DominatorTreeAnaly<wbr>sis>();<br>
              +  PA.preserve<LazyValueAnalysis><wbr>();<br>
                  return PA;<br>
                }<br>
                  bool JumpThreadingPass::runImpl(Fun<wbr>ction &F,
              TargetLibraryInfo *TLI_,<br>
                                                LazyValueInfo *LVI_,
              AliasAnalysis *AA_,<br>
              -                                bool HasProfileData_,<br>
              +                                DeferredDominance *DDT_,
              bool HasProfileData_,<br>
                                               
              std::unique_ptr<BlockFrequency<wbr>Info> BFI_,<br>
                                               
              std::unique_ptr<BranchProbabil<wbr>ityInfo> BPI_) {<br>
                  DEBUG(dbgs() << "Jump threading on function '"
              << F.getName() << "'\n");<br>
                  TLI = TLI_;<br>
                  LVI = LVI_;<br>
                  AA = AA_;<br>
              +  DDT = DDT_;<br>
                  BFI.reset();<br>
                  BPI.reset();<br>
                  // When profile data is available, we need to update
              edge weights after<br>
              @@ -353,7 +365,7 @@ bool JumpThreadingPass::runImpl(Fun<wbr>ction<br>
                  // back edges. This works for normal cases but not for
              unreachable blocks as<br>
                  // they may have cycle with no back edge.<br>
                  bool EverChanged = false;<br>
              -  EverChanged |= removeUnreachableBlocks(F, LVI);<br>
              +  EverChanged |= removeUnreachableBlocks(F, LVI, DDT);<br>
                    FindLoopHeaders(F);<br>
                @@ -368,6 +380,10 @@ bool JumpThreadingPass::runImpl(Fun<wbr>ction<br>
                        ++I;<br>
                +      // Don't thread branches over a block that's
              slated for deletion.<br>
              +      if (DDT->pendingDeletedBB(BB))<br>
              +        continue;<br>
              +<br>
                      // If the block is trivially dead, zap it.  This
              eliminates the successor<br>
                      // edges which simplifies the CFG.<br>
                      if (pred_empty(BB) &&<br>
              @@ -376,7 +392,7 @@ bool JumpThreadingPass::runImpl(Fun<wbr>ction<br>
                              << "' with terminator: " <<
              *BB->getTerminator() << '\n');<br>
                        LoopHeaders.erase(BB);<br>
                        LVI->eraseBlock(BB);<br>
              -        DeleteDeadBlock(BB);<br>
              +        DeleteDeadBlock(BB, DDT);<br>
                        Changed = true;<br>
                        continue;<br>
                      }<br>
              @@ -400,7 +416,7 @@ bool JumpThreadingPass::runImpl(Fun<wbr>ction<br>
                        // awesome, but it allows us to use AssertingVH
              to prevent nasty<br>
                        // dangling pointer issues within LazyValueInfo.<br>
                        LVI->eraseBlock(BB);<br>
              -        if (TryToSimplifyUncondBranchFrom<wbr>EmptyBlock(BB))<br>
              +        if (TryToSimplifyUncondBranchFrom<wbr>EmptyBlock(BB,
              DDT))<br>
                          Changed = true;<br>
                      }<br>
                    }<br>
              @@ -408,6 +424,7 @@ bool JumpThreadingPass::runImpl(Fun<wbr>ction<br>
                  } while (Changed);<br>
                    LoopHeaders.clear();<br>
              +  DDT->flush();<br>
                  return EverChanged;<br>
                }<br>
                @@ -931,8 +948,8 @@ static bool
              hasAddressTakenAndUsed(Basic<br>
                bool JumpThreadingPass::ProcessBloc<wbr>k(BasicBlock
              *BB) {<br>
                  // If the block is trivially dead, just return and let
              the caller nuke it.<br>
                  // This simplifies other transformations.<br>
              -  if (pred_empty(BB) &&<br>
              -      BB != &BB->getParent()->getEntryBloc<wbr>k())<br>
              +  if (DDT->pendingDeletedBB(BB) ||<br>
              +      (pred_empty(BB) && BB !=
              &BB->getParent()->getEntryBloc<wbr>k()))<br>
                    return false;<br>
                    // If this block has a single predecessor, and if
              that pred has a single<br>
              @@ -948,7 +965,7 @@ bool JumpThreadingPass::ProcessBloc<wbr>k(Bas<br>
                        LoopHeaders.insert(BB);<br>
                        LVI->eraseBlock(SinglePred);<br>
              -      MergeBasicBlockIntoOnlyPred(BB<wbr>);<br>
              +      MergeBasicBlockIntoOnlyPred(BB<wbr>, nullptr, DDT);<br>
                        // Now that BB is merged into SinglePred (i.e.
              SinglePred Code followed by<br>
                      // BB code within one basic block `BB`), we need
              to invalidate the LVI<br>
              @@ -1031,18 +1048,23 @@ bool
              JumpThreadingPass::ProcessBloc<wbr>k(Bas<br>
                  // successors to branch to.  Let
              GetBestDestForJumpOnUndef decide.<br>
                  if (isa<UndefValue>(Condition)) {<br>
                    unsigned BestSucc = GetBestDestForJumpOnUndef(BB);<br>
              +    std::vector<DominatorTree::Upd<wbr>ateType>
              Updates;<br>
                      // Fold the branch/switch.<br>
                    TerminatorInst *BBTerm = BB->getTerminator();<br>
              +    Updates.reserve(BBTerm->getNum<wbr>Successors());<br>
                    for (unsigned i = 0, e =
              BBTerm->getNumSuccessors(); i != e; ++i) {<br>
                      if (i == BestSucc) continue;<br>
              -      BBTerm->getSuccessor(i)->remov<wbr>ePredecessor(BB,
              true);<br>
              +      BasicBlock *Succ = BBTerm->getSuccessor(i);<br>
              +      Succ->removePredecessor(BB, true);<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete, BB,
              Succ});<br>
                    }<br>
                      DEBUG(dbgs() << "  In block '" <<
              BB->getName()<br>
                          << "' folding undef terminator: "
              << *BBTerm << '\n');<br>
                    BranchInst::Create(BBTerm->get<wbr>Successor(BestSucc),
              BBTerm);<br>
                    BBTerm->eraseFromParent();<br>
              +    DDT->applyUpdates(Updates);<br>
                    return true;<br>
                  }<br>
                @@ -1053,7 +1075,7 @@ bool
              JumpThreadingPass::ProcessBloc<wbr>k(Bas<br>
                    DEBUG(dbgs() << "  In block '" <<
              BB->getName()<br>
                          << "' folding terminator: " <<
              *BB->getTerminator() << '\n');<br>
                    ++NumFolds;<br>
              -    ConstantFoldTerminator(BB, true);<br>
              +    ConstantFoldTerminator(BB, true, nullptr, DDT);<br>
                    return true;<br>
                  }<br>
                @@ -1086,7 +1108,8 @@ bool
              JumpThreadingPass::ProcessBloc<wbr>k(Bas<br>
                      if (Ret != LazyValueInfo::Unknown) {<br>
                        unsigned ToRemove = Ret == LazyValueInfo::True ?
              1 : 0;<br>
                        unsigned ToKeep = Ret == LazyValueInfo::True ? 0
              : 1;<br>
              -        CondBr->getSuccessor(ToRemove)<wbr>->removePredecessor(BB,
              true);<br>
              +        BasicBlock *ToRemoveSucc =
              CondBr->getSuccessor(ToRemove)<wbr>;<br>
              +        ToRemoveSucc->removePredecesso<wbr>r(BB,
              true);<br>
                        BranchInst::Create(CondBr->get<wbr>Successor(ToKeep),
              CondBr);<br>
                        CondBr->eraseFromParent();<br>
                        if (CondCmp->use_empty())<br>
              @@ -1104,6 +1127,7 @@ bool JumpThreadingPass::ProcessBloc<wbr>k(Bas<br>
                            ConstantInt::getFalse(CondCmp-<wbr>>getType());<br>
                          ReplaceFoldableUses(CondCmp, CI);<br>
                        }<br>
              +        DDT->deleteEdge(BB, ToRemoveSucc);<br>
                        return true;<br>
                      }<br>
                @@ -1182,9 +1206,12 @@ bool
              JumpThreadingPass::ProcessImpl<wbr>iedCo<br>
                    Optional<bool> Implication =<br>
                        isImpliedCondition(PBI->getCon<wbr>dition(),
              Cond, DL, CondIsTrue);<br>
                    if (Implication) {<br>
              -      BI->getSuccessor(*Implication ? 1 :
              0)->removePredecessor(BB);<br>
              -      BranchInst::Create(BI->getSucc<wbr>essor(*Implication
              ? 0 : 1), BI);<br>
              +      BasicBlock *KeepSucc =
              BI->getSuccessor(*Implication ? 0 : 1);<br>
              +      BasicBlock *RemoveSucc =
              BI->getSuccessor(*Implication ? 1 : 0);<br>
              +      RemoveSucc->removePredecessor(<wbr>BB);<br>
              +      BranchInst::Create(KeepSucc, BI);<br>
                      BI->eraseFromParent();<br>
              +      DDT->deleteEdge(BB, RemoveSucc);<br>
                      return true;<br>
                    }<br>
                    CurrentBB = CurrentPred;<br>
              @@ -1591,17 +1618,22 @@ bool
              JumpThreadingPass::ProcessThre<wbr>adabl<br>
                    if (PredWithKnownDest ==<br>
                        (size_t)std::distance(pred_beg<wbr>in(BB),
              pred_end(BB))) {<br>
                      bool SeenFirstBranchToOnlyDest = false;<br>
              +      std::vector <DominatorTree::UpdateType>
              Updates;<br>
              +      Updates.reserve(BB->getTermina<wbr>tor()->getNumSuccessors()
              - 1);<br>
                      for (BasicBlock *SuccBB : successors(BB)) {<br>
              -        if (SuccBB == OnlyDest &&
              !SeenFirstBranchToOnlyDest)<br>
              +        if (SuccBB == OnlyDest &&
              !SeenFirstBranchToOnlyDest) {<br>
                          SeenFirstBranchToOnlyDest = true; // Don't
              modify the first branch.<br>
              -        else<br>
              +        } else {<br>
                          SuccBB->removePredecessor(BB, true); //
              This is unreachable successor.<br>
              +          Updates.push_back({DominatorTr<wbr>ee::Delete,
              BB, SuccBB});<br>
              +        }<br>
                      }<br>
                        // Finally update the terminator.<br>
                      TerminatorInst *Term = BB->getTerminator();<br>
                      BranchInst::Create(OnlyDest, Term);<br>
                      Term->eraseFromParent();<br>
              +      DDT->applyUpdates(Updates);<br>
                        // If the condition is now dead due to the
              removal of the old terminator,<br>
                      // erase it.<br>
              @@ -1964,6 +1996,10 @@ bool JumpThreadingPass::ThreadEdge(<wbr>Basic<br>
                      PredTerm->setSuccessor(i, NewBB);<br>
                    }<br>
                +  DDT->applyUpdates({{DominatorT<wbr>ree::Insert,
              NewBB, SuccBB},<br>
              +                     {DominatorTree::Insert, PredBB,
              NewBB},<br>
              +                     {DominatorTree::Delete, PredBB,
              BB}});<br>
              +<br>
                  // At this point, the IR is fully up to date and
              consistent.  Do a quick scan<br>
                  // over the new instructions and zap any that are
              constants or dead.  This<br>
                  // frequently happens because of phi translation.<br>
              @@ -1983,20 +2019,42 @@ bool
              JumpThreadingPass::ThreadEdge(<wbr>Basic<br>
                BasicBlock *JumpThreadingPass::SplitBlock<wbr>Preds(BasicBlock
              *BB,<br>
                                                             
               ArrayRef<BasicBlock *> Preds,<br>
                                                               const
              char *Suffix) {<br>
              +  SmallVector<BasicBlock *, 2> NewBBs;<br>
              +<br>
                  // Collect the frequencies of all predecessors of BB,
              which will be used to<br>
              -  // update the edge weight on BB->SuccBB.<br>
              -  BlockFrequency PredBBFreq(0);<br>
              +  // update the edge weight of the result of splitting
              predecessors.<br>
              +  DenseMap<BasicBlock *, BlockFrequency> FreqMap;<br>
                  if (HasProfileData)<br>
                    for (auto Pred : Preds)<br>
              -      PredBBFreq += BFI->getBlockFreq(Pred) *
              BPI->getEdgeProbability(Pred, BB);<br>
              +      FreqMap.insert(std::make_pair(<br>
              +          Pred, BFI->getBlockFreq(Pred) *
              BPI->getEdgeProbability(Pred, BB)));<br>
              +<br>
              +  // In the case when BB is a LandingPad block we create
              2 new predecessors<br>
              +  // instead of just one.<br>
              +  if (BB->isLandingPad()) {<br>
              +    std::string NewName = std::string(Suffix) +
              ".split-lp";<br>
              +    SplitLandingPadPredecessors(BB<wbr>, Preds, Suffix,
              NewName.c_str(), NewBBs);<br>
              +  } else {<br>
              +    NewBBs.push_back(SplitBlockPre<wbr>decessors(BB,
              Preds, Suffix));<br>
              +  }<br>
                -  BasicBlock *PredBB = SplitBlockPredecessors(BB,
              Preds, Suffix);<br>
              +  std::vector<DominatorTree::Upd<wbr>ateType>
              Updates;<br>
              +  Updates.reserve((2 * Preds.size()) + NewBBs.size());<br>
              +  for (auto NewBB : NewBBs) {<br>
              +    BlockFrequency NewBBFreq(0);<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Insert, NewBB,
              BB});<br>
              +    for (auto Pred : predecessors(NewBB)) {<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete,
              Pred, BB});<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Insert,
              Pred, NewBB});<br>
              +      if (HasProfileData) // Update frequencies between
              Pred -> NewBB.<br>
              +        NewBBFreq += FreqMap.lookup(Pred);<br>
              +    }<br>
              +    if (HasProfileData) // Apply the summed frequency to
              NewBB.<br>
              +      BFI->setBlockFreq(NewBB,
              NewBBFreq.getFrequency());<br>
              +  }<br>
                -  // Set the block frequency of the newly created
              PredBB, which is the sum of<br>
              -  // frequencies of Preds.<br>
              -  if (HasProfileData)<br>
              -    BFI->setBlockFreq(PredBB,
              PredBBFreq.getFrequency());<br>
              -  return PredBB;<br>
              +  DDT->applyUpdates(Updates);<br>
              +  return NewBBs[0];<br>
                }<br>
                  bool JumpThreadingPass::doesBlockHa<wbr>veProfileData(BasicBlock
              *BB) {<br>
              @@ -2140,6 +2198,7 @@ bool JumpThreadingPass::DuplicateCo<wbr>ndBra<br>
                  }<br>
                    // And finally, do it!  Start by factoring the
              predecessors if needed.<br>
              +  std::vector<DominatorTree::Upd<wbr>ateType>
              Updates;<br>
                  BasicBlock *PredBB;<br>
                  if (PredBBs.size() == 1)<br>
                    PredBB = PredBBs[0];<br>
              @@ -2148,6 +2207,7 @@ bool JumpThreadingPass::DuplicateCo<wbr>ndBra<br>
                          << " common predecessors.\n");<br>
                    PredBB = SplitBlockPreds(BB, PredBBs, ".thr_comm");<br>
                  }<br>
              +  Updates.push_back({DominatorTr<wbr>ee::Delete, PredBB,
              BB});<br>
                    // Okay, we decided to do this!  Clone all the
              instructions in BB onto the end<br>
                  // of PredBB.<br>
              @@ -2160,7 +2220,11 @@ bool JumpThreadingPass::DuplicateCo<wbr>ndBra<br>
                  BranchInst *OldPredBranch =
              dyn_cast<BranchInst>(PredBB->g<wbr>etTerminator());<br>
                    if (!OldPredBranch ||
              !OldPredBranch->isUnconditiona<wbr>l()) {<br>
              -    PredBB = SplitEdge(PredBB, BB);<br>
              +    BasicBlock *OldPredBB = PredBB;<br>
              +    PredBB = SplitEdge(OldPredBB, BB);<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Insert,
              OldPredBB, PredBB});<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Insert,
              PredBB, BB});<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Delete,
              OldPredBB, BB});<br>
                    OldPredBranch =
              cast<BranchInst>(PredBB->getTe<wbr>rminator());<br>
                  }<br>
                @@ -2202,6 +2266,10 @@ bool
              JumpThreadingPass::DuplicateCo<wbr>ndBra<br>
                      // Otherwise, insert the new instruction into the
              block.<br>
                      New->setName(BI->getName());<br>
                      PredBB->getInstList().insert(O<wbr>ldPredBranch->getIterator(),
              New);<br>
              +      // Update Dominance from simplified New instruction
              operands.<br>
              +      for (unsigned i = 0, e = New->getNumOperands();
              i != e; ++i)<br>
              +        if (BasicBlock *SuccBB =
              dyn_cast<BasicBlock>(New->getO<wbr>perand(i)))<br>
              +          Updates.push_back({DominatorTr<wbr>ee::Insert,
              PredBB, SuccBB});<br>
                    }<br>
                  }<br>
                @@ -2257,6 +2325,7 @@ bool
              JumpThreadingPass::DuplicateCo<wbr>ndBra<br>
                    // Remove the unconditional branch at the end of the
              PredBB block.<br>
                  OldPredBranch->eraseFromParent<wbr>();<br>
              +  DDT->applyUpdates(Updates);<br>
                    ++NumDupes;<br>
                  return true;<br>
              @@ -2329,6 +2398,8 @@ bool JumpThreadingPass::TryToUnfold<wbr>Selec<br>
                      // The select is now dead.<br>
                      SI->eraseFromParent();<br>
                +      DDT->applyUpdates({{DominatorT<wbr>ree::Insert,
              NewBB, BB},<br>
              +                         {DominatorTree::Insert, Pred,
              NewBB}});<br>
                      // Update any other PHI nodes in BB.<br>
                      for (BasicBlock::iterator BI = BB->begin();<br>
                           PHINode *Phi = dyn_cast<PHINode>(BI);
              ++BI)<br>
              @@ -2407,11 +2478,25 @@ bool
              JumpThreadingPass::TryToUnfold<wbr>Selec<br>
                    // Expand the select.<br>
                    TerminatorInst *Term =<br>
                        SplitBlockAndInsertIfThen(SI-><wbr>getCondition(),
              SI, false);<br>
              +    BasicBlock *SplitBB = SI->getParent();<br>
              +    BasicBlock *NewBB = Term->getParent();<br>
                    PHINode *NewPN = PHINode::Create(SI->getType(),
              2, "", SI);<br>
                    NewPN->addIncoming(SI->getTrue<wbr>Value(),
              Term->getParent());<br>
                    NewPN->addIncoming(SI->getFals<wbr>eValue(),
              BB);<br>
                    SI->replaceAllUsesWith(NewPN);<br>
                    SI->eraseFromParent();<br>
              +    // NewBB and SplitBB are newly created blocks which
              require insertion.<br>
              +    std::vector<DominatorTree::Upd<wbr>ateType>
              Updates;<br>
              +    Updates.reserve((2 *
              SplitBB->getTerminator()->getN<wbr>umSuccessors()) +
              3);<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Insert, BB,
              SplitBB});<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Insert, BB,
              NewBB});<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Insert, NewBB,
              SplitBB});<br>
              +    // BB's successors were moved to SplitBB, update DDT
              accordingly.<br>
              +    for (auto *Succ : successors(SplitBB)) {<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete, BB,
              Succ});<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Insert,
              SplitBB, Succ});<br>
              +    }<br>
              +    DDT->applyUpdates(Updates);<br>
                    return true;<br>
                  }<br>
                  return false;<br>
              @@ -2498,8 +2583,8 @@ bool JumpThreadingPass::ThreadGuard<wbr>(Basi<br>
                  if (!TrueDestIsSafe && !FalseDestIsSafe)<br>
                    return false;<br>
                -  BasicBlock *UnguardedBlock = TrueDestIsSafe ?
              TrueDest : FalseDest;<br>
              -  BasicBlock *GuardedBlock = FalseDestIsSafe ? TrueDest :
              FalseDest;<br>
              +  BasicBlock *PredUnguardedBlock = TrueDestIsSafe ?
              TrueDest : FalseDest;<br>
              +  BasicBlock *PredGuardedBlock = FalseDestIsSafe ?
              TrueDest : FalseDest;<br>
                    ValueToValueMapTy UnguardedMapping, GuardedMapping;<br>
                  Instruction *AfterGuard = Guard->getNextNode();<br>
              @@ -2508,18 +2593,29 @@ bool
              JumpThreadingPass::ThreadGuard<wbr>(Basi<br>
                    return false;<br>
                  // Duplicate all instructions before the guard and the
              guard itself to the<br>
                  // branch where implication is not proved.<br>
              -  GuardedBlock = DuplicateInstructionsInSplitBe<wbr>tween(<br>
              -      BB, GuardedBlock, AfterGuard, GuardedMapping);<br>
              +  BasicBlock *GuardedBlock =
              DuplicateInstructionsInSplitBe<wbr>tween(<br>
              +      BB, PredGuardedBlock, AfterGuard, GuardedMapping);<br>
                  assert(GuardedBlock && "Could not create the
              guarded block?");<br>
                  // Duplicate all instructions before the guard in the
              unguarded branch.<br>
                  // Since we have successfully duplicated the guarded
              block and this block<br>
                  // has fewer instructions, we expect it to succeed.<br>
              -  UnguardedBlock = DuplicateInstructionsInSplitBe<wbr>tween(BB,
              UnguardedBlock,<br>
              -                                                     
               Guard, UnguardedMapping);<br>
              +  BasicBlock *UnguardedBlock =
              DuplicateInstructionsInSplitBe<wbr>tween(<br>
              +      BB, PredUnguardedBlock, Guard, UnguardedMapping);<br>
                  assert(UnguardedBlock && "Could not create the
              unguarded block?");<br>
                  DEBUG(dbgs() << "Moved guard " << *Guard
              << " to block "<br>
                               << GuardedBlock->getName()
              << "\n");<br>
              -<br>
              +  // DuplicateInstructionsInSplitBe<wbr>tween inserts a
              new block "BB.split" between<br>
              +  // PredBB and BB. We need to perform two inserts and
              one delete for each of<br>
              +  // the above calls to update Dominators.<br>
              +  DDT->applyUpdates(<br>
              +      {// Guarded block split.<br>
              +       {DominatorTree::Delete, PredGuardedBlock, BB},<br>
              +       {DominatorTree::Insert, PredGuardedBlock,
              GuardedBlock},<br>
              +       {DominatorTree::Insert, GuardedBlock, BB},<br>
              +       // Unguarded block split.<br>
              +       {DominatorTree::Delete, PredUnguardedBlock, BB},<br>
              +       {DominatorTree::Insert, PredUnguardedBlock,
              UnguardedBlock},<br>
              +       {DominatorTree::Insert, UnguardedBlock, BB}});<br>
                  // Some instructions before the guard may still have
              uses. For them, we need<br>
                  // to create Phi nodes merging their copies in both
              guarded and unguarded<br>
                  // branches. Those instructions that have no uses can
              be just removed.<br>
              <br>
              Modified: llvm/trunk/lib/Transforms/Util<wbr>s/BasicBlockUtils.cpp<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/BasicBlockUtils.cpp?<wbr>rev=321825&r1=321824&r2=<wbr>321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/lib/Transforms/Util<wbr>s/BasicBlockUtils.cpp
              (original)<br>
              +++ llvm/trunk/lib/Transforms/Util<wbr>s/BasicBlockUtils.cpp
              Thu Jan  4 13:57:32 2018<br>
              @@ -45,16 +45,22 @@<br>
                  using namespace llvm;<br>
                -void llvm::DeleteDeadBlock(BasicBlo<wbr>ck *BB) {<br>
              +void llvm::DeleteDeadBlock(BasicBlo<wbr>ck *BB,
              DeferredDominance *DDT) {<br>
                  assert((pred_begin(BB) == pred_end(BB) ||<br>
                         // Can delete self loop.<br>
                         BB->getSinglePredecessor() == BB) &&
              "Block is not dead!");<br>
                  TerminatorInst *BBTerm = BB->getTerminator();<br>
              +  std::vector<DominatorTree::Upd<wbr>ateType>
              Updates;<br>
                    // Loop through all of our successors and make sure
              they know that one<br>
                  // of their predecessors is going away.<br>
              -  for (BasicBlock *Succ : BBTerm->successors())<br>
              +  if (DDT)<br>
              +    Updates.reserve(BBTerm->getNum<wbr>Successors());<br>
              +  for (BasicBlock *Succ : BBTerm->successors()) {<br>
                    Succ->removePredecessor(BB);<br>
              +    if (DDT)<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete, BB,
              Succ});<br>
              +  }<br>
                    // Zap all the instructions in the block.<br>
                  while (!BB->empty()) {<br>
              @@ -69,8 +75,12 @@ void llvm::DeleteDeadBlock(BasicBlo<wbr>ck
              *B<br>
                    BB->getInstList().pop_back();<br>
                  }<br>
                -  // Zap the block!<br>
              -  BB->eraseFromParent();<br>
              +  if (DDT) {<br>
              +    DDT->applyUpdates(Updates);<br>
              +    DDT->deleteBB(BB); // Deferred deletion of BB.<br>
              +  } else {<br>
              +    BB->eraseFromParent(); // Zap the block!<br>
              +  }<br>
                }<br>
                  void llvm::FoldSingleEntryPHINodes(<wbr>BasicBlock
              *BB,<br>
              <br>
              Modified: llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/Local.cpp?rev=321825&<wbr>r1=321824&r2=321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp
              (original)<br>
              +++ llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp Thu
              Jan  4 13:57:32 2018<br>
              @@ -100,7 +100,8 @@ STATISTIC(NumRemoved, "Number of
              unreach<br>
                /// conditions and indirectbr addresses this might make
              dead if<br>
                /// DeleteDeadConditions is true.<br>
                bool llvm::ConstantFoldTerminator(B<wbr>asicBlock *BB,
              bool DeleteDeadConditions,<br>
              -                                  const TargetLibraryInfo
              *TLI) {<br>
              +                                  const TargetLibraryInfo
              *TLI,<br>
              +                                  DeferredDominance *DDT)
              {<br>
                  TerminatorInst *T = BB->getTerminator();<br>
                  IRBuilder<> Builder(T);<br>
                @@ -123,6 +124,8 @@ bool llvm::ConstantFoldTerminator(B<wbr>asicB<br>
                      // Replace the conditional branch with an
              unconditional one.<br>
                      Builder.CreateBr(Destination);<br>
                      BI->eraseFromParent();<br>
              +      if (DDT)<br>
              +        DDT->deleteEdge(BB, OldDest);<br>
                      return true;<br>
                    }<br>
                @@ -193,9 +196,12 @@ bool llvm::ConstantFoldTerminator(B<wbr>asicB<br>
                                          createBranchWeights(Weights));<br>
                        }<br>
                        // Remove this entry.<br>
              -        DefaultDest->removePredecessor<wbr>(SI->getParent());<br>
              +        BasicBlock *ParentBB = SI->getParent();<br>
              +        DefaultDest->removePredecessor<wbr>(ParentBB);<br>
                        i = SI->removeCase(i);<br>
                        e = SI->case_end();<br>
              +        if (DDT)<br>
              +          DDT->deleteEdge(ParentBB, DefaultDest);<br>
                        continue;<br>
                      }<br>
                @@ -221,14 +227,20 @@ bool
              llvm::ConstantFoldTerminator(B<wbr>asicB<br>
                      // Insert the new branch.<br>
                      Builder.CreateBr(TheOnlyDest);<br>
                      BasicBlock *BB = SI->getParent();<br>
              +      std::vector <DominatorTree::UpdateType>
              Updates;<br>
              +      if (DDT)<br>
              +        Updates.reserve(SI->getNumSucc<wbr>essors() -
              1);<br>
                        // Remove entries from PHI nodes which we no
              longer branch to...<br>
                      for (BasicBlock *Succ : SI->successors()) {<br>
                        // Found case matching a constant operand?<br>
              -        if (Succ == TheOnlyDest)<br>
              +        if (Succ == TheOnlyDest) {<br>
                          TheOnlyDest = nullptr; // Don't modify the
              first branch to TheOnlyDest<br>
              -        else<br>
              +        } else {<br>
                          Succ->removePredecessor(BB);<br>
              +          if (DDT)<br>
              +            Updates.push_back({DominatorTr<wbr>ee::Delete,
              BB, Succ});<br>
              +        }<br>
                      }<br>
                        // Delete the old switch.<br>
              @@ -236,6 +248,8 @@ bool llvm::ConstantFoldTerminator(B<wbr>asicB<br>
                      SI->eraseFromParent();<br>
                      if (DeleteDeadConditions)<br>
                        RecursivelyDeleteTriviallyDead<wbr>Instructions(Cond,
              TLI);<br>
              +      if (DDT)<br>
              +        DDT->applyUpdates(Updates);<br>
                      return true;<br>
                    }<br>
                @@ -281,14 +295,23 @@ bool
              llvm::ConstantFoldTerminator(B<wbr>asicB<br>
                    if (auto *BA =<br>
                          dyn_cast<BlockAddress>(IBI->ge<wbr>tAddress()->stripPointerCasts(<wbr>)))
              {<br>
                      BasicBlock *TheOnlyDest = BA->getBasicBlock();<br>
              +      std::vector <DominatorTree::UpdateType>
              Updates;<br>
              +      if (DDT)<br>
              +        Updates.reserve(IBI->getNumDes<wbr>tinations()
              - 1);<br>
              +<br>
                      // Insert the new branch.<br>
                      Builder.CreateBr(TheOnlyDest);<br>
                        for (unsigned i = 0, e =
              IBI->getNumDestinations(); i != e; ++i) {<br>
              -        if (IBI->getDestination(i) == TheOnlyDest)<br>
              +        if (IBI->getDestination(i) == TheOnlyDest) {<br>
                          TheOnlyDest = nullptr;<br>
              -        else<br>
              -          IBI->getDestination(i)->remove<wbr>Predecessor(IBI->getParent());<br>
              +        } else {<br>
              +          BasicBlock *ParentBB = IBI->getParent();<br>
              +          BasicBlock *DestBB = IBI->getDestination(i);<br>
              +          DestBB->removePredecessor(Pare<wbr>ntBB);<br>
              +          if (DDT)<br>
              +            Updates.push_back({DominatorTr<wbr>ee::Delete,
              ParentBB, DestBB});<br>
              +        }<br>
                      }<br>
                      Value *Address = IBI->getAddress();<br>
                      IBI->eraseFromParent();<br>
              @@ -303,6 +326,8 @@ bool llvm::ConstantFoldTerminator(B<wbr>asicB<br>
                        new UnreachableInst(BB->getContext<wbr>(),
              BB);<br>
                      }<br>
                +      if (DDT)<br>
              +        DDT->applyUpdates(Updates);<br>
                      return true;<br>
                    }<br>
                  }<br>
              @@ -579,7 +604,8 @@ bool llvm::SimplifyInstructionsInBl<wbr>ock(B<br>
                ///<br>
                /// .. and delete the predecessor corresponding to the
              '1', this will attempt to<br>
                /// recursively fold the and to 0.<br>
              -void llvm::RemovePredecessorAndSimp<wbr>lify(BasicBlock
              *BB, BasicBlock *Pred) {<br>
              +void llvm::RemovePredecessorAndSimp<wbr>lify(BasicBlock
              *BB, BasicBlock *Pred,<br>
              +                                        DeferredDominance
              *DDT) {<br>
                  // This only adjusts blocks with PHI nodes.<br>
                  if (!isa<PHINode>(BB->begin()))<br>
                    return;<br>
              @@ -602,13 +628,18 @@ void llvm::RemovePredecessorAndSimp<wbr>lify(<br>
                    // of the block.<br>
                    if (PhiIt != OldPhiIt) PhiIt = &BB->front();<br>
                  }<br>
              +  if (DDT)<br>
              +    DDT->deleteEdge(Pred, BB);<br>
                }<br>
                  /// MergeBasicBlockIntoOnlyPred - DestBB is a block
              with one predecessor and its<br>
                /// predecessor is known to have one successor
              (DestBB!).  Eliminate the edge<br>
                /// between them, moving the instructions in the
              predecessor into DestBB and<br>
                /// deleting the predecessor block.<br>
              -void llvm::MergeBasicBlockIntoOnlyP<wbr>red(BasicBlock
              *DestBB, DominatorTree *DT) {<br>
              +void llvm::MergeBasicBlockIntoOnlyP<wbr>red(BasicBlock
              *DestBB, DominatorTree *DT,<br>
              +                                       DeferredDominance
              *DDT) {<br>
              +  assert(!(DT && DDT) && "Cannot call
              with both DT and DDT.");<br>
              +<br>
                  // If BB has single-entry PHI nodes, fold them.<br>
                  while (PHINode *PN =
              dyn_cast<PHINode>(DestBB->begi<wbr>n())) {<br>
                    Value *NewVal = PN->getIncomingValue(0);<br>
              @@ -621,6 +652,23 @@ void llvm::MergeBasicBlockIntoOnlyP<wbr>red(B<br>
                  BasicBlock *PredBB = DestBB->getSinglePredecessor()<wbr>;<br>
                  assert(PredBB && "Block doesn't have a single
              predecessor!");<br>
                +  bool ReplaceEntryBB = false;<br>
              +  if (PredBB == &DestBB->getParent()->getEntry<wbr>Block())<br>
              +    ReplaceEntryBB = true;<br>
              +<br>
              +  // Deferred DT update: Collect all the edges that enter
              PredBB. These<br>
              +  // dominator edges will be redirected to DestBB.<br>
              +  std::vector <DominatorTree::UpdateType> Updates;<br>
              +  if (DDT && !ReplaceEntryBB) {<br>
              +    Updates.reserve((2 * std::distance(pred_begin(PredB<wbr>B),
              pred_end(PredBB))) +<br>
              +                    1);<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Delete,
              PredBB, DestBB});<br>
              +    for (auto I = pred_begin(PredBB), E =
              pred_end(PredBB); I != E; ++I) {<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete, *I,
              PredBB});<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Insert, *I,
              DestBB});<br>
              +    }<br>
              +  }<br>
              +<br>
                  // Zap anything that took the address of DestBB.  Not
              doing this will give the<br>
                  // address an invalid value.<br>
                  if (DestBB->hasAddressTaken()) {<br>
              @@ -641,7 +689,7 @@ void llvm::MergeBasicBlockIntoOnlyP<wbr>red(B<br>
                    // If the PredBB is the entry block of the function,
              move DestBB up to<br>
                  // become the entry block after we erase PredBB.<br>
              -  if (PredBB == &DestBB->getParent()->getEntry<wbr>Block())<br>
              +  if (ReplaceEntryBB)<br>
                    DestBB->moveAfter(PredBB);<br>
                    if (DT) {<br>
              @@ -653,8 +701,19 @@ void llvm::MergeBasicBlockIntoOnlyP<wbr>red(B<br>
                      DT->eraseNode(PredBB);<br>
                    }<br>
                  }<br>
              -  // Nuke BB.<br>
              -  PredBB->eraseFromParent();<br>
              +<br>
              +  if (DDT) {<br>
              +    DDT->deleteBB(PredBB); // Deferred deletion of BB.<br>
              +    if (ReplaceEntryBB)<br>
              +      // The entry block was removed and there is no
              external interface for the<br>
              +      // dominator tree to be notified of this change. In
              this corner-case we<br>
              +      // recalculate the entire tree.<br>
              +      DDT->recalculate(*(DestBB->get<wbr>Parent()));<br>
              +    else<br>
              +      DDT->applyUpdates(Updates);<br>
              +  } else {<br>
              +    PredBB->eraseFromParent(); // Nuke BB.<br>
              +  }<br>
                }<br>
                  /// CanMergeValues - Return true if we can choose one
              of these values to use<br>
              @@ -861,7 +920,8 @@ static void
              redirectValuesFromPredecesso<br>
                /// potential side-effect free intrinsics and the
              branch.  If possible,<br>
                /// eliminate BB by rewriting all the predecessors to
              branch to the successor<br>
                /// block and return true.  If we can't transform,
              return false.<br>
              -bool llvm::TryToSimplifyUncondBranc<wbr>hFromEmptyBlock(BasicBlock
              *BB) {<br>
              +bool llvm::TryToSimplifyUncondBranc<wbr>hFromEmptyBlock(BasicBlock
              *BB,<br>
              +                                                 
               DeferredDominance *DDT) {<br>
                  assert(BB != &BB->getParent()->getEntryBloc<wbr>k()
              &&<br>
                         "TryToSimplifyUncondBranchFro<wbr>mEmptyBlock
              called on entry block!");<br>
                @@ -902,6 +962,17 @@ bool llvm::TryToSimplifyUncondBranc<wbr>hFrom<br>
                    DEBUG(dbgs() << "Killing Trivial BB: \n"
              << *BB);<br>
                +  std::vector<DominatorTree::Upd<wbr>ateType>
              Updates;<br>
              +  if (DDT) {<br>
              +    Updates.reserve((2 * std::distance(pred_begin(BB),
              pred_end(BB))) + 1);<br>
              +    Updates.push_back({DominatorTr<wbr>ee::Delete, BB,
              Succ});<br>
              +    // All predecessors of BB will be moved to Succ.<br>
              +    for (auto I = pred_begin(BB), E = pred_end(BB); I !=
              E; ++I) {<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete, *I,
              BB});<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Insert, *I,
              Succ});<br>
              +    }<br>
              +  }<br>
              +<br>
                  if (isa<PHINode>(Succ->begin())) {<br>
                    // If there is more than one pred of succ, and there
              are PHI nodes in<br>
                    // the successor, then we need to add incoming edges
              for the PHI nodes<br>
              @@ -946,7 +1017,13 @@ bool llvm::TryToSimplifyUncondBranc<wbr>hFrom<br>
                  // Everything that jumped to BB now goes to Succ.<br>
                  BB->replaceAllUsesWith(Succ);<br>
                  if (!Succ->hasName()) Succ->takeName(BB);<br>
              -  BB->eraseFromParent();              // Delete the
              old basic block.<br>
              +<br>
              +  if (DDT) {<br>
              +    DDT->deleteBB(BB); // Deferred deletion of the old
              basic block.<br>
              +    DDT->applyUpdates(Updates);<br>
              +  } else {<br>
              +    BB->eraseFromParent(); // Delete the old basic
              block.<br>
              +  }<br>
                  return true;<br>
                }<br>
                @@ -1448,13 +1525,19 @@ unsigned
              llvm::removeAllNonTerminatorAn<wbr>d<br>
                }<br>
                  unsigned llvm::changeToUnreachable(Inst<wbr>ruction
              *I, bool UseLLVMTrap,<br>
              -                                   bool PreserveLCSSA) {<br>
              +                                   bool PreserveLCSSA,
              DeferredDominance *DDT) {<br>
                  BasicBlock *BB = I->getParent();<br>
              +  std::vector <DominatorTree::UpdateType> Updates;<br>
              +<br>
                  // Loop over all of the successors, removing BB's
              entry from any PHI<br>
                  // nodes.<br>
              -  for (BasicBlock *Successor : successors(BB))<br>
              +  if (DDT)<br>
              +    Updates.reserve(BB->getTermina<wbr>tor()->getNumSuccessors());<br>
              +  for (BasicBlock *Successor : successors(BB)) {<br>
                    Successor->removePredecessor(B<wbr>B,
              PreserveLCSSA);<br>
              -<br>
              +    if (DDT)<br>
              +      Updates.push_back({DominatorTr<wbr>ee::Delete, BB,
              Successor});<br>
              +  }<br>
                  // Insert a call to llvm.trap right before this.  This
              turns the undefined<br>
                  // behavior into a hard fail instead of falling
              through into random code.<br>
                  if (UseLLVMTrap) {<br>
              @@ -1474,11 +1557,13 @@ unsigned
              llvm::changeToUnreachable(Inst<wbr>r<br>
                    BB->getInstList().erase(BBI++)<wbr>;<br>
                    ++NumInstrsRemoved;<br>
                  }<br>
              +  if (DDT)<br>
              +    DDT->applyUpdates(Updates);<br>
                  return NumInstrsRemoved;<br>
                }<br>
                  /// changeToCall - Convert the specified invoke into a
              normal call.<br>
              -static void changeToCall(InvokeInst *II) {<br>
              +static void changeToCall(InvokeInst *II,
              DeferredDominance *DDT = nullptr) {<br>
                  SmallVector<Value*, 8> Args(II->arg_begin(),
              II->arg_end());<br>
                  SmallVector<OperandBundleDef, 1> OpBundles;<br>
                  II->getOperandBundlesAsDefs(Op<wbr>Bundles);<br>
              @@ -1491,11 +1576,16 @@ static void
              changeToCall(InvokeInst *II)<br>
                  II->replaceAllUsesWith(NewCall<wbr>);<br>
                    // Follow the call by a branch to the normal
              destination.<br>
              -  BranchInst::Create(II->getNorm<wbr>alDest(), II);<br>
              +  BasicBlock *NormalDestBB = II->getNormalDest();<br>
              +  BranchInst::Create(NormalDestB<wbr>B, II);<br>
                    // Update PHI nodes in the unwind destination<br>
              -  II->getUnwindDest()->removePre<wbr>decessor(II->getParent());<br>
              +  BasicBlock *BB = II->getParent();<br>
              +  BasicBlock *UnwindDestBB = II->getUnwindDest();<br>
              +  UnwindDestBB->removePredecesso<wbr>r(BB);<br>
                  II->eraseFromParent();<br>
              +  if (DDT)<br>
              +    DDT->deleteEdge(BB, UnwindDestBB);<br>
                }<br>
                  BasicBlock *llvm::changeToInvokeAndSplitB<wbr>asicBlock(CallInst
              *CI,<br>
              @@ -1536,7 +1626,8 @@ BasicBlock
              *llvm::changeToInvokeAndSplit<br>
                }<br>
                  static bool markAliveBlocks(Function &F,<br>
              -                           
              SmallPtrSetImpl<BasicBlock*> &Reachable) {<br>
              +                           
              SmallPtrSetImpl<BasicBlock*> &Reachable,<br>
              +                            DeferredDominance *DDT =
              nullptr) {<br>
                  SmallVector<BasicBlock*, 128> Worklist;<br>
                  BasicBlock *BB = &F.front();<br>
                  Worklist.push_back(BB);<br>
              @@ -1556,7 +1647,7 @@ static bool markAliveBlocks(Function
              &F,<br>
                        if (II->getIntrinsicID() ==
              Intrinsic::assume) {<br>
                          if (match(II->getArgOperand(0),
              m_CombineOr(m_Zero(), m_Undef()))) {<br>
                            // Don't insert a call to llvm.trap right
              before the unreachable.<br>
              -            changeToUnreachable(II, false);<br>
              +            changeToUnreachable(II, false, false, DDT);<br>
                            Changed = true;<br>
                            break;<br>
                          }<br>
              @@ -1573,7 +1664,8 @@ static bool markAliveBlocks(Function
              &F,<br>
                          // still be useful for widening.<br>
                          if (match(II->getArgOperand(0), m_Zero()))<br>
                            if (!isa<UnreachableInst>(II->get<wbr>NextNode()))
              {<br>
              -              changeToUnreachable(II->getNex<wbr>tNode(),
              /*UseLLVMTrap=*/ false);<br>
              +              changeToUnreachable(II->getNex<wbr>tNode(),
              /*UseLLVMTrap=*/false,<br>
              +                                  false, DDT);<br>
                              Changed = true;<br>
                              break;<br>
                            }<br>
              @@ -1583,7 +1675,7 @@ static bool markAliveBlocks(Function
              &F,<br>
                      if (auto *CI = dyn_cast<CallInst>(&I)) {<br>
                        Value *Callee = CI->getCalledValue();<br>
                        if (isa<ConstantPointerNull>(Call<wbr>ee)
              || isa<UndefValue>(Callee)) {<br>
              -          changeToUnreachable(CI, /*UseLLVMTrap=*/false);<br>
              +          changeToUnreachable(CI, /*UseLLVMTrap=*/false,
              false, DDT);<br>
                          Changed = true;<br>
                          break;<br>
                        }<br>
              @@ -1593,7 +1685,7 @@ static bool markAliveBlocks(Function
              &F,<br>
                          // though.<br>
                          if (!isa<UnreachableInst>(CI->get<wbr>NextNode()))
              {<br>
                            // Don't insert a call to llvm.trap right
              before the unreachable.<br>
              -            changeToUnreachable(CI->getNex<wbr>tNode(),
              false);<br>
              +            changeToUnreachable(CI->getNex<wbr>tNode(),
              false, false, DDT);<br>
                            Changed = true;<br>
                          }<br>
                          break;<br>
              @@ -1612,7 +1704,7 @@ static bool markAliveBlocks(Function
              &F,<br>
                        if (isa<UndefValue>(Ptr) ||<br>
                            (isa<ConstantPointerNull>(Ptr)
              &&<br>
                             SI->getPointerAddressSpace() == 0)) {<br>
              -          changeToUnreachable(SI, true);<br>
              +          changeToUnreachable(SI, true, false, DDT);<br>
                          Changed = true;<br>
                          break;<br>
                        }<br>
              @@ -1624,16 +1716,20 @@ static bool
              markAliveBlocks(Function &F,<br>
                      // Turn invokes that call 'nounwind' functions
              into ordinary calls.<br>
                      Value *Callee = II->getCalledValue();<br>
                      if (isa<ConstantPointerNull>(Call<wbr>ee) ||
              isa<UndefValue>(Callee)) {<br>
              -        changeToUnreachable(II, true);<br>
              +        changeToUnreachable(II, true, false, DDT);<br>
                        Changed = true;<br>
                      } else if (II->doesNotThrow() &&
              canSimplifyInvokeNoUnwind(&F)) {<br>
                        if (II->use_empty() &&
              II->onlyReadsMemory()) {<br>
                          // jump to the normal destination branch.<br>
              -          BranchInst::Create(II->getNorm<wbr>alDest(),
              II);<br>
              -          II->getUnwindDest()->removePre<wbr>decessor(II->getParent());<br>
              +          BasicBlock *NormalDestBB =
              II->getNormalDest();<br>
              +          BasicBlock *UnwindDestBB =
              II->getUnwindDest();<br>
              +          BranchInst::Create(NormalDestB<wbr>B, II);<br>
              +          UnwindDestBB->removePredecesso<wbr>r(II->getParent());<br>
                          II->eraseFromParent();<br>
              +          if (DDT)<br>
              +            DDT->deleteEdge(BB, UnwindDestBB);<br>
                        } else<br>
              -          changeToCall(II);<br>
              +          changeToCall(II, DDT);<br>
                        Changed = true;<br>
                      }<br>
                    } else if (auto *CatchSwitch =
              dyn_cast<CatchSwitchInst>(Term<wbr>inator)) {<br>
              @@ -1679,7 +1775,7 @@ static bool markAliveBlocks(Function
              &F,<br>
                      }<br>
                    }<br>
                -    Changed |= ConstantFoldTerminator(BB, true);<br>
              +    Changed |= ConstantFoldTerminator(BB, true, nullptr,
              DDT);<br>
                    for (BasicBlock *Successor : successors(BB))<br>
                      if (Reachable.insert(Successor).s<wbr>econd)<br>
                        Worklist.push_back(Successor);<br>
              @@ -1687,11 +1783,11 @@ static bool
              markAliveBlocks(Function &F,<br>
                  return Changed;<br>
                }<br>
                -void llvm::removeUnwindEdge(BasicBl<wbr>ock *BB) {<br>
              +void llvm::removeUnwindEdge(BasicBl<wbr>ock *BB,
              DeferredDominance *DDT) {<br>
                  TerminatorInst *TI = BB->getTerminator();<br>
                    if (auto *II = dyn_cast<InvokeInst>(TI)) {<br>
              -    changeToCall(II);<br>
              +    changeToCall(II, DDT);<br>
                    return;<br>
                  }<br>
                @@ -1719,15 +1815,18 @@ void
              llvm::removeUnwindEdge(BasicBl<wbr>ock *<br>
                  UnwindDest->removePredecessor(<wbr>BB);<br>
                  TI->replaceAllUsesWith(NewTI);<br>
                  TI->eraseFromParent();<br>
              +  if (DDT)<br>
              +    DDT->deleteEdge(BB, UnwindDest);<br>
                }<br>
                  /// removeUnreachableBlocks - Remove blocks that are
              not reachable, even<br>
                /// if they are in a dead cycle.  Return true if a
              change was made, false<br>
                /// otherwise. If `LVI` is passed, this function
              preserves LazyValueInfo<br>
                /// after modifying the CFG.<br>
              -bool llvm::removeUnreachableBlocks(<wbr>Function &F,
              LazyValueInfo *LVI) {<br>
              +bool llvm::removeUnreachableBlocks(<wbr>Function &F,
              LazyValueInfo *LVI,<br>
              +                                   DeferredDominance
              *DDT) {<br>
                  SmallPtrSet<BasicBlock*, 16> Reachable;<br>
              -  bool Changed = markAliveBlocks(F, Reachable);<br>
              +  bool Changed = markAliveBlocks(F, Reachable, DDT);<br>
                    // If there are unreachable blocks in the CFG...<br>
                  if (Reachable.size() == F.size())<br>
              @@ -1737,25 +1836,39 @@ bool
              llvm::removeUnreachableBlocks(<wbr>Funct<br>
                  NumRemoved += F.size()-Reachable.size();<br>
                    // Loop over all of the basic blocks that are not
              reachable, dropping all of<br>
              -  // their internal references...<br>
              -  for (Function::iterator BB = ++F.begin(), E = F.end();
              BB != E; ++BB) {<br>
              -    if (Reachable.count(&*BB))<br>
              +  // their internal references. Update DDT and LVI if
              available.<br>
              +  std::vector <DominatorTree::UpdateType> Updates;<br>
              +  for (Function::iterator I = ++F.begin(), E = F.end(); I
              != E; ++I) {<br>
              +    auto *BB = &*I;<br>
              +    if (Reachable.count(BB))<br>
                      continue;<br>
              -<br>
              -    for (BasicBlock *Successor : successors(&*BB))<br>
              +    for (BasicBlock *Successor : successors(BB)) {<br>
                      if (Reachable.count(Successor))<br>
              -        Successor->removePredecessor(&<wbr>*BB);<br>
              +        Successor->removePredecessor(B<wbr>B);<br>
              +      if (DDT)<br>
              +        Updates.push_back({DominatorTr<wbr>ee::Delete,
              BB, Successor});<br>
              +    }<br>
                    if (LVI)<br>
              -      LVI->eraseBlock(&*BB);<br>
              +      LVI->eraseBlock(BB);<br>
                    BB->dropAllReferences();<br>
                  }<br>
                -  for (Function::iterator I = ++F.begin(); I !=
              F.end();)<br>
              -    if (!Reachable.count(&*I))<br>
              -      I = F.getBasicBlockList().erase(I)<wbr>;<br>
              -    else<br>
              +  for (Function::iterator I = ++F.begin(); I != F.end();)
              {<br>
              +    auto *BB = &*I;<br>
              +    if (Reachable.count(BB)) {<br>
              +      ++I;<br>
              +      continue;<br>
              +    }<br>
              +    if (DDT) {<br>
              +      DDT->deleteBB(BB); // deferred deletion of BB.<br>
                      ++I;<br>
              +    } else {<br>
              +      I = F.getBasicBlockList().erase(I)<wbr>;<br>
              +    }<br>
              +  }<br>
                +  if (DDT)<br>
              +    DDT->applyUpdates(Updates);<br>
                  return true;<br>
                }<br>
                <br>
              Modified: llvm/trunk/test/Analysis/LazyV<wbr>alueAnalysis/lvi-after-jumpthr<wbr>eading.ll<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll?rev=321825&r1=321824&r2=321825&view=diff"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Analysis<wbr>/LazyValueAnalysis/lvi-after-<wbr>jumpthreading.ll?rev=321825&<wbr>r1=321824&r2=321825&view=diff</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/test/Analysis/LazyV<wbr>alueAnalysis/lvi-after-jumpthr<wbr>eading.ll
              (original)<br>
              +++ llvm/trunk/test/Analysis/LazyV<wbr>alueAnalysis/lvi-after-jumpthr<wbr>eading.ll
              Thu Jan  4 13:57:32 2018<br>
              @@ -19,10 +19,13 @@ entry:<br>
                ; CHECK-NEXT:     ; LatticeVal for: 'i32 %a' is:
              overdefined<br>
                ; CHECK-NEXT:     ; LatticeVal for: 'i32 %length' is:
              overdefined<br>
                ; CHECK-NEXT:     ; LatticeVal for: '  %iv = phi i32 [
              0, %entry ], [ %iv.next, %backedge ]' in BB: '%backedge'
              is: constantrange<0, 400><br>
              +; CHECK-NEXT:     ; LatticeVal for: '  %iv = phi i32 [ 0,
              %entry ], [ %iv.next, %backedge ]' in BB: '%exit' is:
              constantrange<399, 400><br>
                ; CHECK-NEXT:  %iv = phi i32 [ 0, %entry ], [ %iv.next,
              %backedge ]<br>
                ; CHECK-NEXT:     ; LatticeVal for: '  %iv.next = add
              nsw i32 %iv, 1' in BB: '%backedge' is: constantrange<1,
              401><br>
              +; CHECK-NEXT:     ; LatticeVal for: '  %iv.next = add nsw
              i32 %iv, 1' in BB: '%exit' is: constantrange<400,
              401><br>
                ; CHECK-NEXT:  %iv.next = add nsw i32 %iv, 1<br>
                ; CHECK-NEXT:     ; LatticeVal for: '  %cont = icmp slt
              i32 %iv.next, 400' in BB: '%backedge' is: overdefined<br>
              +; CHECK-NEXT:     ; LatticeVal for: '  %cont = icmp slt
              i32 %iv.next, 400' in BB: '%exit' is: constantrange<0,
              -1><br>
                ; CHECK-NEXT:  %cont = icmp slt i32 %iv.next, 400<br>
                ; CHECK-NOT: loop<br>
                loop:<br>
              <br>
              Added: llvm/trunk/test/Transforms/Jum<wbr>pThreading/ddt-crash.ll<br>
              URL: <a
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll?rev=321825&view=auto"
                rel="noreferrer" target="_blank" moz-do-not-send="true">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/JumpThreading/ddt-crash.ll?<wbr>rev=321825&view=auto</a><br>
              ==============================<wbr>==============================<wbr>==================<br>
              --- llvm/trunk/test/Transforms/Jum<wbr>pThreading/ddt-crash.ll
              (added)<br>
              +++ llvm/trunk/test/Transforms/Jum<wbr>pThreading/ddt-crash.ll
              Thu Jan  4 13:57:32 2018<br>
              @@ -0,0 +1,265 @@<br>
              +; RUN: opt < %s -jump-threading -disable-output<br>
              +<br>
              +%struct.ham = type { i8, i8, i16, i32 }<br>
              +%struct.zot = type { i32 (...)** }<br>
              +%struct.quux.0 = type { %struct.wombat }<br>
              +%struct.wombat = type { %struct.zot }<br>
              +<br>
              +@global = external global %struct.ham*, align 8<br>
              +@global.1 = external constant i8*<br>
              +<br>
              +declare i32 @wombat.2()<br>
              +<br>
              +define void @blam() {<br>
              +bb:<br>
              +  %tmp = load i32, i32* undef<br>
              +  %tmp1 = icmp eq i32 %tmp, 0<br>
              +  br i1 %tmp1, label %bb11, label %bb2<br>
              +<br>
              +bb2:<br>
              +  %tmp3 = tail call i32 @wombat.2()<br>
              +  switch i32 %tmp3, label %bb4 [<br>
              +    i32 0, label %bb5<br>
              +    i32 1, label %bb7<br>
              +    i32 2, label %bb7<br>
              +    i32 3, label %bb11<br>
              +  ]<br>
              +<br>
              +bb4:<br>
              +  br label %bb7<br>
              +<br>
              +bb5:<br>
              +  %tmp6 = tail call i32 @wombat.2()<br>
              +  br label %bb7<br>
              +<br>
              +bb7:<br>
              +  %tmp8 = phi i32 [ 0, %bb5 ], [ 1, %bb4 ], [ 2, %bb2 ],
              [ 2, %bb2 ]<br>
              +  %tmp9 = icmp eq i32 %tmp8, 0<br>
              +  br i1 %tmp9, label %bb11, label %bb10<br>
              +<br>
              +bb10:<br>
              +  ret void<br>
              +<br>
              +bb11:<br>
              +  ret void<br>
              +}<br>
              +<br>
              +define void @spam(%struct.ham* %arg) {<br>
              +bb:<br>
              +  %tmp = load i8, i8* undef, align 8<br>
              +  switch i8 %tmp, label %bb11 [<br>
              +    i8 1, label %bb11<br>
              +    i8 2, label %bb11<br>
              +    i8 3, label %bb1<br>
              +    i8 4, label %bb1<br>
              +  ]<br>
              +<br>
              +bb1:<br>
              +  br label %bb2<br>
              +<br>
              +bb2:<br>
              +  %tmp3 = phi i32 [ 0, %bb1 ], [ %tmp3, %bb8 ]<br>
              +  br label %bb4<br>
              +<br>
              +bb4:<br>
              +  %tmp5 = load i8, i8* undef, align 8<br>
              +  switch i8 %tmp5, label %bb11 [<br>
              +    i8 0, label %bb11<br>
              +    i8 1, label %bb10<br>
              +    i8 2, label %bb10<br>
              +    i8 3, label %bb6<br>
              +    i8 4, label %bb6<br>
              +  ]<br>
              +<br>
              +bb6:<br>
              +  br label %bb7<br>
              +<br>
              +bb7:<br>
              +  br i1 undef, label %bb8, label %bb10<br>
              +<br>
              +bb8:<br>
              +  %tmp9 = icmp eq %struct.ham* undef, %arg<br>
              +  br i1 %tmp9, label %bb10, label %bb2<br>
              +<br>
              +bb10:<br>
              +  switch i32 %tmp3, label %bb4 [<br>
              +    i32 0, label %bb14<br>
              +    i32 1, label %bb11</blockquote>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
    <br>
  </body>
</html>