[llvm] r311057 - Reapply: [ADCE][Dominators] Teach ADCE to preserve dominators

Jakub (Kuba) Kuderski via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 21 10:24:50 PDT 2017


Hi Daniel,

Thanks for reporting the bug.

Would I be right in thinking that TreeNodePtr::getLevel() returns the depth
> in the dominator tree?

Correct.

 If so, I think that the update to indicate that %four dominates %exit when
> the %switch->%default path is deleted is causing %exit to be misidentified
> as unreachable in the later updates because DescendAndCollect() is only
> checking the depth of the successors it finds. If %exit had been updated
> after all the removals then it would have turned out ok.

I don't have any recent LLVM revision on my machine at the moment, so it's
a bit difficult for me to follow just the description. I'll take a look at
it tomorrow. In the meanwhile, feel free to revert the ADCE patch.

Best,
Kuba

On Mon, Aug 21, 2017 at 7:11 PM, Daniel Sanders <daniel_l_sanders at apple.com>
wrote:

> Hi,
>
> I'm currently seeing a crash in ADCE which I've narrowed down to this
> commit. Given this bugpoint-reduced test case:
> define void @foo() {
> entry:
>   br label %switch
> switch:                    ; preds = %entry
>   switch i32 undef, label %default [
>     i32 2, label %two
>     i32 5, label %five
>     i32 4, label %four
>   ]
> four:                      ; preds = %switch
>   br label %exit
> five:                      ; preds = %switch
>   br label %exit
> two:                       ; preds = %switch
>   br label %exit
> default:                   ; preds = %switch
>   br label %exit
> exit:                      ; preds = %default, %two, %five, %four
>   ret void
> }
> the command './bin/opt bugpoint-reduced-simplified.ll -adce -S -o -'
> asserts with:
> Assertion failed: (TN), function operator(), file
> ../llvm/include/llvm/Support/GenericDomTreeConstruction.h, line 1031.
> Stack dump:
> 0. Program arguments: ./bin/opt bugpoint-reduced-simplified.ll -adce -S
> -o -
> 1. Running pass 'Function Pass Manager' on module
> 'bugpoint-reduced-simplified.ll'.
> 2. Running pass 'Aggressive Dead Code Elimination' on function '@foo'
> Abort trap: 6
>
> According to the -debug output and some additional instrumentation, ADCE
> starts by re-writing the switch to a 'br label %four'. I was expecting it
> to choose %default but all choices are equivalent so it doesn't matter
> much. At this point it deletes the %switch->%default CFG edge, erases
> %default, and updates the dominator tree to indicate that %four dominates
> %exit. It then deletes the %switch->%two CFG edge and it's at this point
> that things start to go wrong.
>
> After deleting the %switch->%two edge it erases %two but it also erases
> %exit which is still being used by %four (as well as %default, %two, and
> %five). The dominator tree is correctly updated to reflect the removal of
> both %two and %exit. It then proceeds to delete the %switch->%five edge and
> hits the assertion when it attempts to look up a TreeNodePtr for %exit and
> doesn't find one.
>
> I'm currently thinking that this is a processing order issue. Would I be
> right in thinking that TreeNodePtr::getLevel() returns the depth in the
> dominator tree? If so, I think that the update to indicate that %four
> dominates %exit when the %switch->%default path is deleted is causing %exit
> to be misidentified as unreachable in the later updates because
> DescendAndCollect() is only checking the depth of the successors it finds.
> If %exit had been updated after all the removals then it would have turned
> out ok.
>
> On 17 Aug 2017, at 02:41, Jakub Kuderski via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
> Author: kuhar
> Date: Wed Aug 16 18:41:49 2017
> New Revision: 311057
>
> URL: http://llvm.org/viewvc/llvm-project?rev=311057&view=rev
> Log:
> Reapply: [ADCE][Dominators] Teach ADCE to preserve dominators
>
> Summary:
> This patch teaches ADCE to preserve both DominatorTrees and
> PostDominatorTrees.
>
> I didn't notice any performance impact when bootstrapping clang with this
> patch.
>
> The patch was originally committed in r311039 and reverted in r311049.
> This revision fixes the problem with not adding a dependency on the
> DominatorTreeWrapperPass for the LegacyPassManager.
>
> Reviewers: dberlin, chandlerc, sanjoy, davide, grosser, brzycki
>
> Reviewed By: davide
>
> Subscribers: grandinj, zhendongsu, llvm-commits, david2050
>
> Differential Revision: https://reviews.llvm.org/D35869
>
> Added:
>    llvm/trunk/test/Transforms/ADCE/domtree-DoubleDeletion.ll
>    llvm/trunk/test/Transforms/ADCE/unreachable.ll
> Modified:
>    llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h
>    llvm/trunk/lib/Transforms/Scalar/ADCE.cpp
>
> Modified: llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/
> GenericDomTreeConstruction.h?rev=311057&r1=311056&r2=311057&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h
> (original)
> +++ llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h Wed Aug
> 16 18:41:49 2017
> @@ -914,7 +914,12 @@ struct SemiNCAInfo {
>     if (!FromTN) return;
>
>     const TreeNodePtr ToTN = DT.getNode(To);
> -    assert(ToTN && "To already unreachable -- there is no edge to
> delete");
> +    if (!ToTN) {
> +      DEBUG(dbgs() << "\tTo (" << BlockNamePrinter(To)
> +                   << ") already unreachable -- there is no edge to
> delete\n");
> +      return;
> +    }
> +
>     const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
>     const TreeNodePtr NCD = DT.getNode(NCDBlock);
>
>
> Modified: llvm/trunk/lib/Transforms/Scalar/ADCE.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/Scalar/ADCE.cpp?rev=311057&r1=311056&r2=311057&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/Scalar/ADCE.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/ADCE.cpp Wed Aug 16 18:41:49 2017
> @@ -27,6 +27,7 @@
> #include "llvm/IR/BasicBlock.h"
> #include "llvm/IR/CFG.h"
> #include "llvm/IR/DebugInfoMetadata.h"
> +#include "llvm/IR/Dominators.h"
> #include "llvm/IR/IRBuilder.h"
> #include "llvm/IR/InstIterator.h"
> #include "llvm/IR/Instructions.h"
> @@ -89,6 +90,10 @@ struct BlockInfoType {
>
> class AggressiveDeadCodeElimination {
>   Function &F;
> +
> +  // ADCE does not use DominatorTree per se, but it updates it to
> preserve the
> +  // analysis.
> +  DominatorTree &DT;
>   PostDominatorTree &PDT;
>
>   /// Mapping of blocks to associated information, an element in
> BlockInfoVec.
> @@ -157,9 +162,10 @@ class AggressiveDeadCodeElimination {
>   void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
>
> public:
> -  AggressiveDeadCodeElimination(Function &F, PostDominatorTree &PDT)
> -      : F(F), PDT(PDT) {}
> -  bool performDeadCodeElimination();
> + AggressiveDeadCodeElimination(Function &F, DominatorTree &DT,
> +                               PostDominatorTree &PDT)
> +     : F(F), DT(DT), PDT(PDT) {}
> + bool performDeadCodeElimination();
> };
> }
>
> @@ -557,14 +563,31 @@ void AggressiveDeadCodeElimination::upda
>     }
>     assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
>            "Failed to find safe successor for dead branch");
> +
> +    // Collect removed successors to update the (Post)DominatorTrees.
> +    SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
>     bool First = true;
>     for (auto *Succ : successors(BB)) {
> -      if (!First || Succ != PreferredSucc->BB)
> +      if (!First || Succ != PreferredSucc->BB) {
>         Succ->removePredecessor(BB);
> -      else
> +        RemovedSuccessors.insert(Succ);
> +      } else
>         First = false;
>     }
>     makeUnconditional(BB, PreferredSucc->BB);
> +
> +    // Inform the dominators about the deleted CFG edges.
> +    for (auto *Succ : RemovedSuccessors) {
> +      // It might have happened that the same successor appeared multiple
> times
> +      // and the CFG edge wasn't really removed.
> +      if (Succ != PreferredSucc->BB) {
> +        DEBUG(dbgs() << "ADCE: Removing (Post)DomTree edge " <<
> BB->getName()
> +                     << " -> " << Succ->getName() << "\n");
> +        DT.deleteEdge(BB, Succ);
> +        PDT.deleteEdge(BB, Succ);
> +      }
> +    }
> +
>     NumBranchesRemoved += 1;
>   }
> }
> @@ -609,6 +632,9 @@ void AggressiveDeadCodeElimination::make
>   InstInfo[NewTerm].Live = true;
>   if (const DILocation *DL = PredTerm->getDebugLoc())
>     NewTerm->setDebugLoc(DL);
> +
> +  InstInfo.erase(PredTerm);
> +  PredTerm->eraseFromParent();
> }
>
> //===-------------------------------------------------------
> ---------------===//
> @@ -617,13 +643,16 @@ void AggressiveDeadCodeElimination::make
> //
> //===-------------------------------------------------------
> ---------------===//
> PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &FAM)
> {
> +  auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
>   auto &PDT = FAM.getResult<PostDominatorTreeAnalysis>(F);
> -  if (!AggressiveDeadCodeElimination(F, PDT).
> performDeadCodeElimination())
> +  if (!AggressiveDeadCodeElimination(F, DT, PDT).
> performDeadCodeElimination())
>     return PreservedAnalyses::all();
>
>   PreservedAnalyses PA;
>   PA.preserveSet<CFGAnalyses>();
>   PA.preserve<GlobalsAA>();
> +  PA.preserve<DominatorTreeAnalysis>();
> +  PA.preserve<PostDominatorTreeAnalysis>();
>   return PA;
> }
>
> @@ -637,14 +666,23 @@ struct ADCELegacyPass : public FunctionP
>   bool runOnFunction(Function &F) override {
>     if (skipFunction(F))
>       return false;
> +
> +    auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>     auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>(
> ).getPostDomTree();
> -    return AggressiveDeadCodeElimination(F, PDT).
> performDeadCodeElimination();
> +    return AggressiveDeadCodeElimination(F, DT, PDT)
> +        .performDeadCodeElimination();
>   }
>
>   void getAnalysisUsage(AnalysisUsage &AU) const override {
> +    // We require DominatorTree here only to update and thus preserve it.
> +    AU.addRequired<DominatorTreeWrapperPass>();
>     AU.addRequired<PostDominatorTreeWrapperPass>();
>     if (!RemoveControlFlowFlag)
>       AU.setPreservesCFG();
> +    else {
> +      AU.addPreserved<DominatorTreeWrapperPass>();
> +      AU.addPreserved<PostDominatorTreeWrapperPass>();
> +    }
>     AU.addPreserved<GlobalsAAWrapperPass>();
>   }
> };
> @@ -653,6 +691,7 @@ struct ADCELegacyPass : public FunctionP
> char ADCELegacyPass::ID = 0;
> INITIALIZE_PASS_BEGIN(ADCELegacyPass, "adce",
>                       "Aggressive Dead Code Elimination", false, false)
> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
> INITIALIZE_PASS_END(ADCELegacyPass, "adce", "Aggressive Dead Code
> Elimination",
>                     false, false)
>
> Added: llvm/trunk/test/Transforms/ADCE/domtree-DoubleDeletion.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/ADCE/domtree-DoubleDeletion.ll?rev=311057&view=auto
> ============================================================
> ==================
> --- llvm/trunk/test/Transforms/ADCE/domtree-DoubleDeletion.ll (added)
> +++ llvm/trunk/test/Transforms/ADCE/domtree-DoubleDeletion.ll Wed Aug 16
> 18:41:49 2017
> @@ -0,0 +1,39 @@
> +; RUN: opt < %s -gvn -simplifycfg -adce | llvm-dis
> +; RUN: opt < %s -gvn -simplifycfg -adce -verify-dom-info | llvm-dis
> +
> +; This test makes sure that the DominatorTree properly handles
> +; deletion of edges that go to forward-unreachable regions.
> +; In this case, %land.end is already forward unreachable when
> +; the DT gets informed about the deletion of %entry -> %land.end.
> +
> + at a = common global i32 0, align 4
> +
> +define i32 @main() {
> +entry:
> +  %retval = alloca i32, align 4
> +  store i32 0, i32* %retval, align 4
> +  %0 = load i32, i32* @a, align 4
> +  %cmp = icmp ne i32 %0, 1
> +  br i1 %cmp, label %land.rhs, label %land.end4
> +
> +land.rhs:                                         ; preds = %entry
> +  %1 = load i32, i32* @a, align 4
> +  %tobool = icmp ne i32 %1, 0
> +  br i1 %tobool, label %land.rhs1, label %land.end
> +
> +land.rhs1:                                        ; preds = %land.rhs
> +  br label %land.end
> +
> +land.end:                                         ; preds = %land.rhs1,
> %land.rhs
> +  %2 = phi i1 [ false, %land.rhs ], [ true, %land.rhs1 ]
> +  %land.ext = zext i1 %2 to i32
> +  %conv = trunc i32 %land.ext to i16
> +  %conv2 = sext i16 %conv to i32
> +  %tobool3 = icmp ne i32 %conv2, 0
> +  br label %land.end4
> +
> +land.end4:                                        ; preds = %land.end,
> %entry
> +  %3 = phi i1 [ false, %entry ], [ %tobool3, %land.end ]
> +  %land.ext5 = zext i1 %3 to i32
> +  ret i32 0
> +}
>
> Added: llvm/trunk/test/Transforms/ADCE/unreachable.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/ADCE/unreachable.ll?rev=311057&view=auto
> ============================================================
> ==================
> --- llvm/trunk/test/Transforms/ADCE/unreachable.ll (added)
> +++ llvm/trunk/test/Transforms/ADCE/unreachable.ll Wed Aug 16 18:41:49
> 2017
> @@ -0,0 +1,18 @@
> +; RUN: opt < %s -adce -simplifycfg | llvm-dis
> +; RUN: opt < %s -passes=adce | llvm-dis
> +
> +define i32 @Test(i32 %A, i32 %B) {
> +BB1:
> +        br label %BB4
> +
> +BB2:            ; No predecessors!
> +        br label %BB3
> +
> +BB3:            ; preds = %BB4, %BB2
> +        %ret = phi i32 [ %X, %BB4 ], [ %B, %BB2 ]               ; <i32>
> [#uses=1]
> +        ret i32 %ret
> +
> +BB4:            ; preds = %BB1
> +        %X = phi i32 [ %A, %BB1 ]               ; <i32> [#uses=1]
> +        br label %BB3
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
>


-- 
Jakub Kuderski
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170821/b842fb34/attachment.html>


More information about the llvm-commits mailing list