1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

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
This commit is contained in:
Jakub Kuderski 2017-08-17 01:41:49 +00:00
parent 75de1ccb08
commit 45d778e4d9
4 changed files with 109 additions and 8 deletions

View File

@ -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);

View File

@ -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::updateDeadRegions() {
}
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::makeUnconditional(BasicBlock *BB,
InstInfo[NewTerm].Live = true;
if (const DILocation *DL = PredTerm->getDebugLoc())
NewTerm->setDebugLoc(DL);
InstInfo.erase(PredTerm);
PredTerm->eraseFromParent();
}
//===----------------------------------------------------------------------===//
@ -617,13 +643,16 @@ void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
//
//===----------------------------------------------------------------------===//
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 FunctionPass {
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 FunctionPass {
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)

View File

@ -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.
@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
}

View File

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