llvm.org GIT mirror llvm / 5288e91
[ADCE][Dominators] Reapply: Teach ADCE to preserve dominators Summary: This patch teaches ADCE to preserve both DominatorTrees and PostDominatorTrees. This is reapplies the original patch r311057 that was reverted in r311381. The previous version wasn't using the batch update api for updating dominators, which in vary rare cases caused assertion failures. This also fixes PR34258. Reviewers: dberlin, chandlerc, sanjoy, davide, grosser, brzycki Reviewed By: davide Subscribers: grandinj, zhendongsu, llvm-commits, david2050 Differential Revision: https://reviews.llvm.org/D35869 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311467 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 2 years ago
4 changed file(s) with 130 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
2626 #include "llvm/IR/BasicBlock.h"
2727 #include "llvm/IR/CFG.h"
2828 #include "llvm/IR/DebugInfoMetadata.h"
29 #include "llvm/IR/Dominators.h"
2930 #include "llvm/IR/IRBuilder.h"
3031 #include "llvm/IR/InstIterator.h"
3132 #include "llvm/IR/Instructions.h"
8889
8990 class AggressiveDeadCodeElimination {
9091 Function &F;
92
93 // ADCE does not use DominatorTree per se, but it updates it to preserve the
94 // analysis.
95 DominatorTree &DT;
9196 PostDominatorTree &PDT;
9297
9398 /// Mapping of blocks to associated information, an element in BlockInfoVec.
156161 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
157162
158163 public:
159 AggressiveDeadCodeElimination(Function &F, PostDominatorTree &PDT)
160 : F(F), PDT(PDT) {}
161 bool performDeadCodeElimination();
164 AggressiveDeadCodeElimination(Function &F, DominatorTree &DT,
165 PostDominatorTree &PDT)
166 : F(F), DT(DT), PDT(PDT) {}
167 bool performDeadCodeElimination();
162168 };
163169 }
164170
556562 }
557563 assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
558564 "Failed to find safe successor for dead branch");
565
566 // Collect removed successors to update the (Post)DominatorTrees.
567 SmallPtrSet RemovedSuccessors;
559568 bool First = true;
560569 for (auto *Succ : successors(BB)) {
561 if (!First || Succ != PreferredSucc->BB)
570 if (!First || Succ != PreferredSucc->BB) {
562571 Succ->removePredecessor(BB);
563 else
572 RemovedSuccessors.insert(Succ);
573 } else
564574 First = false;
565575 }
566576 makeUnconditional(BB, PreferredSucc->BB);
577
578 // Inform the dominators about the deleted CFG edges.
579 SmallVector DeletedEdges;
580 for (auto *Succ : RemovedSuccessors) {
581 // It might have happened that the same successor appeared multiple times
582 // and the CFG edge wasn't really removed.
583 if (Succ != PreferredSucc->BB) {
584 DEBUG(dbgs() << "ADCE: (Post)DomTree edge enqueued for deletion"
585 << BB->getName() << " -> " << Succ->getName() << "\n");
586 DeletedEdges.push_back({DominatorTree::Delete, BB, Succ});
587 }
588 }
589
590 DT.applyUpdates(DeletedEdges);
591 PDT.applyUpdates(DeletedEdges);
592
567593 NumBranchesRemoved += 1;
568594 }
569595 }
608634 InstInfo[NewTerm].Live = true;
609635 if (const DILocation *DL = PredTerm->getDebugLoc())
610636 NewTerm->setDebugLoc(DL);
637
638 InstInfo.erase(PredTerm);
639 PredTerm->eraseFromParent();
611640 }
612641
613642 //===----------------------------------------------------------------------===//
616645 //
617646 //===----------------------------------------------------------------------===//
618647 PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &FAM) {
648 auto &DT = FAM.getResult(F);
619649 auto &PDT = FAM.getResult(F);
620 if (!AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination())
650 if (!AggressiveDeadCodeElimination(F, DT, PDT).performDeadCodeElimination())
621651 return PreservedAnalyses::all();
622652
623653 PreservedAnalyses PA;
624654 PA.preserveSet();
625655 PA.preserve();
656 PA.preserve();
657 PA.preserve();
626658 return PA;
627659 }
628660
636668 bool runOnFunction(Function &F) override {
637669 if (skipFunction(F))
638670 return false;
671
672 auto &DT = getAnalysis().getDomTree();
639673 auto &PDT = getAnalysis().getPostDomTree();
640 return AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination();
674 return AggressiveDeadCodeElimination(F, DT, PDT)
675 .performDeadCodeElimination();
641676 }
642677
643678 void getAnalysisUsage(AnalysisUsage &AU) const override {
679 // We require DominatorTree here only to update and thus preserve it.
680 AU.addRequired();
644681 AU.addRequired();
645682 if (!RemoveControlFlowFlag)
646683 AU.setPreservesCFG();
684 else {
685 AU.addPreserved();
686 AU.addPreserved();
687 }
647688 AU.addPreserved();
648689 }
649690 };
652693 char ADCELegacyPass::ID = 0;
653694 INITIALIZE_PASS_BEGIN(ADCELegacyPass, "adce",
654695 "Aggressive Dead Code Elimination", false, false)
696 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
655697 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
656698 INITIALIZE_PASS_END(ADCELegacyPass, "adce", "Aggressive Dead Code Elimination",
657699 false, false)
0 ; RUN: opt < %s -adce | llvm-dis
1 ; RUN: opt < %s -adce -verify-dom-info | llvm-dis
2
3 define void @foo() {
4 entry:
5 br label %switch
6 switch: ; preds = %entry
7 switch i32 undef, label %default [
8 i32 2, label %two
9 i32 5, label %five
10 i32 4, label %four
11 ]
12 four: ; preds = %switch
13 br label %exit
14 five: ; preds = %switch
15 br label %exit
16 two: ; preds = %switch
17 br label %exit
18 default: ; preds = %switch
19 br label %exit
20 exit: ; preds = %default, %two, %five, %four
21 ret void
22 }
23
0 ; RUN: opt < %s -gvn -simplifycfg -adce | llvm-dis
1 ; RUN: opt < %s -gvn -simplifycfg -adce -verify-dom-info | llvm-dis
2
3 ; This test makes sure that the DominatorTree properly handles
4 ; deletion of edges that go to forward-unreachable regions.
5 ; In this case, %land.end is already forward unreachable when
6 ; the DT gets informed about the deletion of %entry -> %land.end.
7
8 @a = common global i32 0, align 4
9
10 define i32 @main() {
11 entry:
12 %retval = alloca i32, align 4
13 store i32 0, i32* %retval, align 4
14 %0 = load i32, i32* @a, align 4
15 %cmp = icmp ne i32 %0, 1
16 br i1 %cmp, label %land.rhs, label %land.end4
17
18 land.rhs: ; preds = %entry
19 %1 = load i32, i32* @a, align 4
20 %tobool = icmp ne i32 %1, 0
21 br i1 %tobool, label %land.rhs1, label %land.end
22
23 land.rhs1: ; preds = %land.rhs
24 br label %land.end
25
26 land.end: ; preds = %land.rhs1, %land.rhs
27 %2 = phi i1 [ false, %land.rhs ], [ true, %land.rhs1 ]
28 %land.ext = zext i1 %2 to i32
29 %conv = trunc i32 %land.ext to i16
30 %conv2 = sext i16 %conv to i32
31 %tobool3 = icmp ne i32 %conv2, 0
32 br label %land.end4
33
34 land.end4: ; preds = %land.end, %entry
35 %3 = phi i1 [ false, %entry ], [ %tobool3, %land.end ]
36 %land.ext5 = zext i1 %3 to i32
37 ret i32 0
38 }
0 ; RUN: opt < %s -adce -simplifycfg | llvm-dis
1 ; RUN: opt < %s -passes=adce | llvm-dis
2
3 define i32 @Test(i32 %A, i32 %B) {
4 BB1:
5 br label %BB4
6
7 BB2: ; No predecessors!
8 br label %BB3
9
10 BB3: ; preds = %BB4, %BB2
11 %ret = phi i32 [ %X, %BB4 ], [ %B, %BB2 ] ; [#uses=1]
12 ret i32 %ret
13
14 BB4: ; preds = %BB1
15 %X = phi i32 [ %A, %BB1 ] ; [#uses=1]
16 br label %BB3
17 }