forked from OSchip/llvm-project
[SCCP] Simplify CFG in SCCP as well
Currently, we only remove dead blocks and non-feasible edges in IPSCCP, but not in SCCP. I'm not aware of any strong reason for that difference, so this patch updates SCCP to perform the CFG cleanup as well. Compile-time impact seems to be pretty minimal, in the 0.05% geomean range on CTMark. For the test case from https://reviews.llvm.org/D126962#3611579 the result after -sccp now looks like this: define void @test(i1 %c) { entry: br i1 %c, label %unreachable, label %next next: unreachable unreachable: call void @bar() unreachable } -jump-threading does nothing on this, but -simplifycfg will produce the optimal result. Differential Revision: https://reviews.llvm.org/D128796
This commit is contained in:
parent
1e55ec6666
commit
10c531cd5b
|
@ -190,10 +190,14 @@ static bool simplifyInstsInBlock(SCCPSolver &Solver, BasicBlock &BB,
|
|||
return MadeChanges;
|
||||
}
|
||||
|
||||
static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
|
||||
DomTreeUpdater &DTU,
|
||||
BasicBlock *&NewUnreachableBB);
|
||||
|
||||
// runSCCP() - Run the Sparse Conditional Constant Propagation algorithm,
|
||||
// and return true if the function was modified.
|
||||
static bool runSCCP(Function &F, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
const TargetLibraryInfo *TLI, DomTreeUpdater &DTU) {
|
||||
LLVM_DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
|
||||
SCCPSolver Solver(
|
||||
DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; },
|
||||
|
@ -221,13 +225,12 @@ static bool runSCCP(Function &F, const DataLayout &DL,
|
|||
// as we cannot modify the CFG of the function.
|
||||
|
||||
SmallPtrSet<Value *, 32> InsertedValues;
|
||||
SmallVector<BasicBlock *, 8> BlocksToErase;
|
||||
for (BasicBlock &BB : F) {
|
||||
if (!Solver.isBlockExecutable(&BB)) {
|
||||
LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
|
||||
|
||||
++NumDeadBlocks;
|
||||
NumInstRemoved += removeAllNonTerminatorAndEHPadInstructions(&BB).first;
|
||||
|
||||
BlocksToErase.push_back(&BB);
|
||||
MadeChanges = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -236,17 +239,32 @@ static bool runSCCP(Function &F, const DataLayout &DL,
|
|||
NumInstRemoved, NumInstReplaced);
|
||||
}
|
||||
|
||||
// Remove unreachable blocks and non-feasible edges.
|
||||
for (BasicBlock *DeadBB : BlocksToErase)
|
||||
NumInstRemoved += changeToUnreachable(DeadBB->getFirstNonPHI(),
|
||||
/*PreserveLCSSA=*/false, &DTU);
|
||||
|
||||
BasicBlock *NewUnreachableBB = nullptr;
|
||||
for (BasicBlock &BB : F)
|
||||
MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU, NewUnreachableBB);
|
||||
|
||||
for (BasicBlock *DeadBB : BlocksToErase)
|
||||
if (!DeadBB->hasAddressTaken())
|
||||
DTU.deleteBB(DeadBB);
|
||||
|
||||
return MadeChanges;
|
||||
}
|
||||
|
||||
PreservedAnalyses SCCPPass::run(Function &F, FunctionAnalysisManager &AM) {
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
|
||||
if (!runSCCP(F, DL, &TLI))
|
||||
auto *DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
|
||||
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
|
||||
if (!runSCCP(F, DL, &TLI, DTU))
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
auto PA = PreservedAnalyses();
|
||||
PA.preserveSet<CFGAnalyses>();
|
||||
PA.preserve<DominatorTreeAnalysis>();
|
||||
return PA;
|
||||
}
|
||||
|
||||
|
@ -269,7 +287,7 @@ public:
|
|||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.setPreservesCFG();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
}
|
||||
|
||||
// runOnFunction - Run the Sparse Conditional Constant Propagation
|
||||
|
@ -280,7 +298,10 @@ public:
|
|||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
const TargetLibraryInfo *TLI =
|
||||
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
|
||||
return runSCCP(F, DL, TLI);
|
||||
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
|
||||
DomTreeUpdater DTU(DTWP ? &DTWP->getDomTree() : nullptr,
|
||||
DomTreeUpdater::UpdateStrategy::Lazy);
|
||||
return runSCCP(F, DL, TLI, DTU);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -30,9 +30,7 @@ define void @main(i1 %cond) {
|
|||
; CHECK-SCCP: while.cond.loopexit.loopexit:
|
||||
; CHECK-SCCP-NEXT: ret void
|
||||
; CHECK-SCCP: while.body3:
|
||||
; CHECK-SCCP-NEXT: br i1 true, label [[IF_END:%.*]], label [[IF_THEN:%.*]]
|
||||
; CHECK-SCCP: if.then:
|
||||
; CHECK-SCCP-NEXT: br label [[IF_END]]
|
||||
; CHECK-SCCP-NEXT: br label [[IF_END:%.*]]
|
||||
; CHECK-SCCP: if.end:
|
||||
; CHECK-SCCP-NEXT: br i1 [[COND:%.*]], label [[WHILE_COND_LOOPEXIT_LOOPEXIT:%.*]], label [[WHILE_BODY3]]
|
||||
;
|
||||
|
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
define i32 @foo() {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: br i1 undef, label [[T:%.*]], label [[T]]
|
||||
; CHECK: T:
|
||||
; CHECK-NEXT: ret i32 undef
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
br i1 undef, label %T, label %T
|
||||
T:
|
||||
|
|
|
@ -7,19 +7,7 @@ define i32 @main() {
|
|||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[BB:%.*]]
|
||||
; CHECK: bb:
|
||||
; CHECK-NEXT: br i1 undef, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
|
||||
; CHECK: cond_true:
|
||||
; CHECK-NEXT: br i1 undef, label [[BB_BACKEDGE:%.*]], label [[BB12:%.*]]
|
||||
; CHECK: bb.backedge:
|
||||
; CHECK-NEXT: br label [[BB]]
|
||||
; CHECK: cond_false:
|
||||
; CHECK-NEXT: br i1 undef, label [[BB_BACKEDGE]], label [[BB12]]
|
||||
; CHECK: bb12:
|
||||
; CHECK-NEXT: br i1 undef, label [[COND_NEXT18:%.*]], label [[COND_TRUE17:%.*]]
|
||||
; CHECK: cond_true17:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: cond_next18:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
entry:
|
||||
br label %bb
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
; RUN: opt < %s -debug-pass-manager -passes='loop-vectorize,sccp,loop-vectorize' 2>&1 -S | FileCheck --check-prefix=NEW-PM %s
|
||||
|
||||
; Check CFG-only analysis are preserved by SCCP by running it between 2
|
||||
; Check that DT is preserved by SCCP by running it between 2
|
||||
; loop-vectorize runs.
|
||||
|
||||
; NEW-PM-DAG: Running analysis: LoopAnalysis on test
|
||||
; NEW-PM-DAG: Running analysis: DominatorTreeAnalysis on test
|
||||
; NEW-PM: Running pass: SCCPPass on test
|
||||
; NEW-PM: Running analysis: TargetLibraryAnalysis on test
|
||||
; NEW-PM-NOT: Running analysis: LoopAnalysis on test
|
||||
; NEW-PM: Running analysis: LoopAnalysis on test
|
||||
; NEW-PM-NOT: Running analysis: DominatorTreeAnalysis on test
|
||||
; NEW-PM-NOT: Running analysis: AssumptionAnalysis on test
|
||||
; NEW-PM-NOT: Running analysis: TargetLibraryAnalysis on test
|
||||
|
|
|
@ -35,20 +35,17 @@ define i32 @test2(i32 %i0, i32 %j0) {
|
|||
; CHECK-NEXT: BB1:
|
||||
; CHECK-NEXT: br label [[BB2:%.*]]
|
||||
; CHECK: BB2:
|
||||
; CHECK-NEXT: [[K2:%.*]] = phi i32 [ [[K4:%.*]], [[BB7:%.*]] ], [ 0, [[BB1:%.*]] ]
|
||||
; CHECK-NEXT: [[K2:%.*]] = phi i32 [ [[K3:%.*]], [[BB7:%.*]] ], [ 0, [[BB1:%.*]] ]
|
||||
; CHECK-NEXT: [[KCOND:%.*]] = icmp slt i32 [[K2]], 100
|
||||
; CHECK-NEXT: br i1 [[KCOND]], label [[BB3:%.*]], label [[BB4:%.*]]
|
||||
; CHECK: BB3:
|
||||
; CHECK-NEXT: br i1 true, label [[BB5:%.*]], label [[BB6:%.*]]
|
||||
; CHECK-NEXT: br label [[BB5:%.*]]
|
||||
; CHECK: BB4:
|
||||
; CHECK-NEXT: ret i32 1
|
||||
; CHECK: BB5:
|
||||
; CHECK-NEXT: [[K3:%.*]] = add i32 [[K2]], 1
|
||||
; CHECK-NEXT: br label [[BB7]]
|
||||
; CHECK: BB6:
|
||||
; CHECK-NEXT: [[K3]] = add i32 [[K2]], 1
|
||||
; CHECK-NEXT: br label [[BB7]]
|
||||
; CHECK: BB7:
|
||||
; CHECK-NEXT: [[K4]] = phi i32 [ [[K3]], [[BB5]] ], [ undef, [[BB6]] ]
|
||||
; CHECK-NEXT: br label [[BB2]]
|
||||
;
|
||||
BB1:
|
||||
|
|
|
@ -223,8 +223,6 @@ define i1 @float.4_unreachable.defaultenv(float %f, i1 %cmp) #0 {
|
|||
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_TRUE:%.*]], label [[END:%.*]]
|
||||
; CHECK: if.true:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: dead:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[C:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f32(float 1.000000e+00, float 1.000000e+00, metadata !"une", metadata !"fpexcept.ignore") #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
|
@ -251,8 +249,6 @@ define i1 @float.4_unreachable.maytrap(float %f, i1 %cmp) #0 {
|
|||
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_TRUE:%.*]], label [[END:%.*]]
|
||||
; CHECK: if.true:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: dead:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[C:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f32(float 1.000000e+00, float 1.000000e+00, metadata !"une", metadata !"fpexcept.maytrap") #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
|
@ -280,8 +276,6 @@ define i1 @float.4_unreachable.strict(float %f, i1 %cmp) #0 {
|
|||
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_TRUE:%.*]], label [[END:%.*]]
|
||||
; CHECK: if.true:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: dead:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[C:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f32(float 1.000000e+00, float 1.000000e+00, metadata !"une", metadata !"fpexcept.strict") #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
|
|
|
@ -223,8 +223,6 @@ define i1 @float.4_unreachable.defaultenv(float %f, i1 %cmp) #0 {
|
|||
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_TRUE:%.*]], label [[END:%.*]]
|
||||
; CHECK: if.true:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: dead:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[C:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f32(float 1.000000e+00, float 1.000000e+00, metadata !"une", metadata !"fpexcept.ignore") #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
|
@ -251,8 +249,6 @@ define i1 @float.4_unreachable.maytrap(float %f, i1 %cmp) #0 {
|
|||
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_TRUE:%.*]], label [[END:%.*]]
|
||||
; CHECK: if.true:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: dead:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[C:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f32(float 1.000000e+00, float 1.000000e+00, metadata !"une", metadata !"fpexcept.maytrap") #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
|
@ -280,8 +276,6 @@ define i1 @float.4_unreachable.strict(float %f, i1 %cmp) #0 {
|
|||
; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_TRUE:%.*]], label [[END:%.*]]
|
||||
; CHECK: if.true:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: dead:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[C:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f32(float 1.000000e+00, float 1.000000e+00, metadata !"une", metadata !"fpexcept.strict") #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
|
|
|
@ -195,11 +195,11 @@ define void @rotated_loop_2(i32 %x) {
|
|||
; SCCP: bb3:
|
||||
; SCCP-NEXT: br label [[EXIT]]
|
||||
; SCCP: exit:
|
||||
; SCCP-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[BB1]] ], [ 2, [[BB2]] ], [ 5, [[BB3]] ], [ [[A:%.*]], [[EXIT]] ]
|
||||
; SCCP-NEXT: [[A]] = add i32 [[P]], 1
|
||||
; SCCP-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[BB1]] ], [ 2, [[BB2]] ], [ 5, [[BB3]] ]
|
||||
; SCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1
|
||||
; SCCP-NEXT: call void @use(i1 true)
|
||||
; SCCP-NEXT: call void @use(i1 false)
|
||||
; SCCP-NEXT: br i1 false, label [[EXIT]], label [[EXIT_1:%.*]]
|
||||
; SCCP-NEXT: br label [[EXIT_1:%.*]]
|
||||
; SCCP: exit.1:
|
||||
; SCCP-NEXT: ret void
|
||||
;
|
||||
|
@ -451,10 +451,10 @@ define void @foo(i64* %arg) {
|
|||
; SCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]]
|
||||
; SCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1
|
||||
; SCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
|
||||
; SCCP-NEXT: [[TMP0:%.*]] = zext i32 [[TMP9]] to i64
|
||||
; SCCP-NEXT: [[TMP10:%.*]] = zext i32 [[TMP9]] to i64
|
||||
; SCCP-NEXT: br label [[BB11:%.*]]
|
||||
; SCCP: bb11:
|
||||
; SCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP0]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
|
||||
; SCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
|
||||
; SCCP-NEXT: br label [[BB13:%.*]]
|
||||
; SCCP: bb13:
|
||||
; SCCP-NEXT: [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6
|
||||
|
@ -489,10 +489,10 @@ define void @foo(i64* %arg) {
|
|||
; IPSCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]]
|
||||
; IPSCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1
|
||||
; IPSCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
|
||||
; IPSCCP-NEXT: [[TMP0:%.*]] = zext i32 [[TMP9]] to i64
|
||||
; IPSCCP-NEXT: [[TMP10:%.*]] = zext i32 [[TMP9]] to i64
|
||||
; IPSCCP-NEXT: br label [[BB11:%.*]]
|
||||
; IPSCCP: bb11:
|
||||
; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP0]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
|
||||
; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
|
||||
; IPSCCP-NEXT: br label [[BB13:%.*]]
|
||||
; IPSCCP: bb13:
|
||||
; IPSCCP-NEXT: [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6
|
||||
|
|
Loading…
Reference in New Issue