Skip to content

Commit fd5c5c9

Browse files
committed
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 llvm-svn: 311057
1 parent 314a005 commit fd5c5c9

File tree

4 files changed

+109
-8
lines changed

4 files changed

+109
-8
lines changed

llvm/include/llvm/Support/GenericDomTreeConstruction.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,12 @@ struct SemiNCAInfo {
914914
if (!FromTN) return;
915915

916916
const TreeNodePtr ToTN = DT.getNode(To);
917-
assert(ToTN && "To already unreachable -- there is no edge to delete");
917+
if (!ToTN) {
918+
DEBUG(dbgs() << "\tTo (" << BlockNamePrinter(To)
919+
<< ") already unreachable -- there is no edge to delete\n");
920+
return;
921+
}
922+
918923
const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
919924
const TreeNodePtr NCD = DT.getNode(NCDBlock);
920925

llvm/lib/Transforms/Scalar/ADCE.cpp

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/IR/BasicBlock.h"
2828
#include "llvm/IR/CFG.h"
2929
#include "llvm/IR/DebugInfoMetadata.h"
30+
#include "llvm/IR/Dominators.h"
3031
#include "llvm/IR/IRBuilder.h"
3132
#include "llvm/IR/InstIterator.h"
3233
#include "llvm/IR/Instructions.h"
@@ -89,6 +90,10 @@ struct BlockInfoType {
8990

9091
class AggressiveDeadCodeElimination {
9192
Function &F;
93+
94+
// ADCE does not use DominatorTree per se, but it updates it to preserve the
95+
// analysis.
96+
DominatorTree &DT;
9297
PostDominatorTree &PDT;
9398

9499
/// Mapping of blocks to associated information, an element in BlockInfoVec.
@@ -157,9 +162,10 @@ class AggressiveDeadCodeElimination {
157162
void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
158163

159164
public:
160-
AggressiveDeadCodeElimination(Function &F, PostDominatorTree &PDT)
161-
: F(F), PDT(PDT) {}
162-
bool performDeadCodeElimination();
165+
AggressiveDeadCodeElimination(Function &F, DominatorTree &DT,
166+
PostDominatorTree &PDT)
167+
: F(F), DT(DT), PDT(PDT) {}
168+
bool performDeadCodeElimination();
163169
};
164170
}
165171

@@ -557,14 +563,31 @@ void AggressiveDeadCodeElimination::updateDeadRegions() {
557563
}
558564
assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
559565
"Failed to find safe successor for dead branch");
566+
567+
// Collect removed successors to update the (Post)DominatorTrees.
568+
SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
560569
bool First = true;
561570
for (auto *Succ : successors(BB)) {
562-
if (!First || Succ != PreferredSucc->BB)
571+
if (!First || Succ != PreferredSucc->BB) {
563572
Succ->removePredecessor(BB);
564-
else
573+
RemovedSuccessors.insert(Succ);
574+
} else
565575
First = false;
566576
}
567577
makeUnconditional(BB, PreferredSucc->BB);
578+
579+
// Inform the dominators about the deleted CFG edges.
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: Removing (Post)DomTree edge " << BB->getName()
585+
<< " -> " << Succ->getName() << "\n");
586+
DT.deleteEdge(BB, Succ);
587+
PDT.deleteEdge(BB, Succ);
588+
}
589+
}
590+
568591
NumBranchesRemoved += 1;
569592
}
570593
}
@@ -609,6 +632,9 @@ void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
609632
InstInfo[NewTerm].Live = true;
610633
if (const DILocation *DL = PredTerm->getDebugLoc())
611634
NewTerm->setDebugLoc(DL);
635+
636+
InstInfo.erase(PredTerm);
637+
PredTerm->eraseFromParent();
612638
}
613639

614640
//===----------------------------------------------------------------------===//
@@ -617,13 +643,16 @@ void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
617643
//
618644
//===----------------------------------------------------------------------===//
619645
PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &FAM) {
646+
auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
620647
auto &PDT = FAM.getResult<PostDominatorTreeAnalysis>(F);
621-
if (!AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination())
648+
if (!AggressiveDeadCodeElimination(F, DT, PDT).performDeadCodeElimination())
622649
return PreservedAnalyses::all();
623650

624651
PreservedAnalyses PA;
625652
PA.preserveSet<CFGAnalyses>();
626653
PA.preserve<GlobalsAA>();
654+
PA.preserve<DominatorTreeAnalysis>();
655+
PA.preserve<PostDominatorTreeAnalysis>();
627656
return PA;
628657
}
629658

@@ -637,14 +666,23 @@ struct ADCELegacyPass : public FunctionPass {
637666
bool runOnFunction(Function &F) override {
638667
if (skipFunction(F))
639668
return false;
669+
670+
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
640671
auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
641-
return AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination();
672+
return AggressiveDeadCodeElimination(F, DT, PDT)
673+
.performDeadCodeElimination();
642674
}
643675

644676
void getAnalysisUsage(AnalysisUsage &AU) const override {
677+
// We require DominatorTree here only to update and thus preserve it.
678+
AU.addRequired<DominatorTreeWrapperPass>();
645679
AU.addRequired<PostDominatorTreeWrapperPass>();
646680
if (!RemoveControlFlowFlag)
647681
AU.setPreservesCFG();
682+
else {
683+
AU.addPreserved<DominatorTreeWrapperPass>();
684+
AU.addPreserved<PostDominatorTreeWrapperPass>();
685+
}
648686
AU.addPreserved<GlobalsAAWrapperPass>();
649687
}
650688
};
@@ -653,6 +691,7 @@ struct ADCELegacyPass : public FunctionPass {
653691
char ADCELegacyPass::ID = 0;
654692
INITIALIZE_PASS_BEGIN(ADCELegacyPass, "adce",
655693
"Aggressive Dead Code Elimination", false, false)
694+
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
656695
INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
657696
INITIALIZE_PASS_END(ADCELegacyPass, "adce", "Aggressive Dead Code Elimination",
658697
false, false)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: opt < %s -gvn -simplifycfg -adce | llvm-dis
2+
; RUN: opt < %s -gvn -simplifycfg -adce -verify-dom-info | llvm-dis
3+
4+
; This test makes sure that the DominatorTree properly handles
5+
; deletion of edges that go to forward-unreachable regions.
6+
; In this case, %land.end is already forward unreachable when
7+
; the DT gets informed about the deletion of %entry -> %land.end.
8+
9+
@a = common global i32 0, align 4
10+
11+
define i32 @main() {
12+
entry:
13+
%retval = alloca i32, align 4
14+
store i32 0, i32* %retval, align 4
15+
%0 = load i32, i32* @a, align 4
16+
%cmp = icmp ne i32 %0, 1
17+
br i1 %cmp, label %land.rhs, label %land.end4
18+
19+
land.rhs: ; preds = %entry
20+
%1 = load i32, i32* @a, align 4
21+
%tobool = icmp ne i32 %1, 0
22+
br i1 %tobool, label %land.rhs1, label %land.end
23+
24+
land.rhs1: ; preds = %land.rhs
25+
br label %land.end
26+
27+
land.end: ; preds = %land.rhs1, %land.rhs
28+
%2 = phi i1 [ false, %land.rhs ], [ true, %land.rhs1 ]
29+
%land.ext = zext i1 %2 to i32
30+
%conv = trunc i32 %land.ext to i16
31+
%conv2 = sext i16 %conv to i32
32+
%tobool3 = icmp ne i32 %conv2, 0
33+
br label %land.end4
34+
35+
land.end4: ; preds = %land.end, %entry
36+
%3 = phi i1 [ false, %entry ], [ %tobool3, %land.end ]
37+
%land.ext5 = zext i1 %3 to i32
38+
ret i32 0
39+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
; RUN: opt < %s -adce -simplifycfg | llvm-dis
2+
; RUN: opt < %s -passes=adce | llvm-dis
3+
4+
define i32 @Test(i32 %A, i32 %B) {
5+
BB1:
6+
br label %BB4
7+
8+
BB2: ; No predecessors!
9+
br label %BB3
10+
11+
BB3: ; preds = %BB4, %BB2
12+
%ret = phi i32 [ %X, %BB4 ], [ %B, %BB2 ] ; <i32> [#uses=1]
13+
ret i32 %ret
14+
15+
BB4: ; preds = %BB1
16+
%X = phi i32 [ %A, %BB1 ] ; <i32> [#uses=1]
17+
br label %BB3
18+
}

0 commit comments

Comments
 (0)