<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>