llvm.org GIT mirror llvm / 85bef5a
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311057 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 2 years ago
4 changed file(s) with 109 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
913913 if (!FromTN) return;
914914
915915 const TreeNodePtr ToTN = DT.getNode(To);
916 assert(ToTN && "To already unreachable -- there is no edge to delete");
916 if (!ToTN) {
917 DEBUG(dbgs() << "\tTo (" << BlockNamePrinter(To)
918 << ") already unreachable -- there is no edge to delete\n");
919 return;
920 }
921
917922 const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
918923 const TreeNodePtr NCD = DT.getNode(NCDBlock);
919924
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 for (auto *Succ : RemovedSuccessors) {
580 // It might have happened that the same successor appeared multiple times
581 // and the CFG edge wasn't really removed.
582 if (Succ != PreferredSucc->BB) {
583 DEBUG(dbgs() << "ADCE: Removing (Post)DomTree edge " << BB->getName()
584 << " -> " << Succ->getName() << "\n");
585 DT.deleteEdge(BB, Succ);
586 PDT.deleteEdge(BB, Succ);
587 }
588 }
589
567590 NumBranchesRemoved += 1;
568591 }
569592 }
608631 InstInfo[NewTerm].Live = true;
609632 if (const DILocation *DL = PredTerm->getDebugLoc())
610633 NewTerm->setDebugLoc(DL);
634
635 InstInfo.erase(PredTerm);
636 PredTerm->eraseFromParent();
611637 }
612638
613639 //===----------------------------------------------------------------------===//
616642 //
617643 //===----------------------------------------------------------------------===//
618644 PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &FAM) {
645 auto &DT = FAM.getResult(F);
619646 auto &PDT = FAM.getResult(F);
620 if (!AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination())
647 if (!AggressiveDeadCodeElimination(F, DT, PDT).performDeadCodeElimination())
621648 return PreservedAnalyses::all();
622649
623650 PreservedAnalyses PA;
624651 PA.preserveSet();
625652 PA.preserve();
653 PA.preserve();
654 PA.preserve();
626655 return PA;
627656 }
628657
636665 bool runOnFunction(Function &F) override {
637666 if (skipFunction(F))
638667 return false;
668
669 auto &DT = getAnalysis().getDomTree();
639670 auto &PDT = getAnalysis().getPostDomTree();
640 return AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination();
671 return AggressiveDeadCodeElimination(F, DT, PDT)
672 .performDeadCodeElimination();
641673 }
642674
643675 void getAnalysisUsage(AnalysisUsage &AU) const override {
676 // We require DominatorTree here only to update and thus preserve it.
677 AU.addRequired();
644678 AU.addRequired();
645679 if (!RemoveControlFlowFlag)
646680 AU.setPreservesCFG();
681 else {
682 AU.addPreserved();
683 AU.addPreserved();
684 }
647685 AU.addPreserved();
648686 }
649687 };
652690 char ADCELegacyPass::ID = 0;
653691 INITIALIZE_PASS_BEGIN(ADCELegacyPass, "adce",
654692 "Aggressive Dead Code Elimination", false, false)
693 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
655694 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
656695 INITIALIZE_PASS_END(ADCELegacyPass, "adce", "Aggressive Dead Code Elimination",
657696 false, false)
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 }