[llvm] 10c531c - [SCCP] Simplify CFG in SCCP as well

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 30 00:25:11 PDT 2022


Author: Nikita Popov
Date: 2022-06-30T09:25:03+02:00
New Revision: 10c531cd5bf0166ce5bf42736506733b2285fdf8

URL: https://github.com/llvm/llvm-project/commit/10c531cd5bf0166ce5bf42736506733b2285fdf8
DIFF: https://github.com/llvm/llvm-project/commit/10c531cd5bf0166ce5bf42736506733b2285fdf8.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/SCCP.cpp
    llvm/test/Transforms/GVN/gvn-loop-load-pre-order.ll
    llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll
    llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll
    llvm/test/Transforms/SCCP/preserve-analysis.ll
    llvm/test/Transforms/SCCP/sccptest.ll
    llvm/test/Transforms/SCCP/strictfp-phis-fcmp.ll
    llvm/test/Transforms/SCCP/strictfp-phis-fcmps.ll
    llvm/test/Transforms/SCCP/widening.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp
index 4dfeb6fd41606..2282ef6360767 100644
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp
@@ -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 @@ class SCCPLegacyPass : public FunctionPass {
   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 @@ class SCCPLegacyPass : public FunctionPass {
     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);
   }
 };
 

diff  --git a/llvm/test/Transforms/GVN/gvn-loop-load-pre-order.ll b/llvm/test/Transforms/GVN/gvn-loop-load-pre-order.ll
index 972e6037a7046..ab5a1f60b20ac 100644
--- a/llvm/test/Transforms/GVN/gvn-loop-load-pre-order.ll
+++ b/llvm/test/Transforms/GVN/gvn-loop-load-pre-order.ll
@@ -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]]
 ;

diff  --git a/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll b/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll
index 271cab2ebe615..2098b0390b64a 100644
--- a/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll
+++ b/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll
@@ -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:

diff  --git a/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll b/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll
index 47903f719caac..6f499f27a65a9 100644
--- a/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll
+++ b/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll
@@ -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

diff  --git a/llvm/test/Transforms/SCCP/preserve-analysis.ll b/llvm/test/Transforms/SCCP/preserve-analysis.ll
index 86ae5d9a9375e..7e61f9ba5fb78 100644
--- a/llvm/test/Transforms/SCCP/preserve-analysis.ll
+++ b/llvm/test/Transforms/SCCP/preserve-analysis.ll
@@ -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

diff  --git a/llvm/test/Transforms/SCCP/sccptest.ll b/llvm/test/Transforms/SCCP/sccptest.ll
index e42d804b27872..299645435bf86 100644
--- a/llvm/test/Transforms/SCCP/sccptest.ll
+++ b/llvm/test/Transforms/SCCP/sccptest.ll
@@ -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:

diff  --git a/llvm/test/Transforms/SCCP/strictfp-phis-fcmp.ll b/llvm/test/Transforms/SCCP/strictfp-phis-fcmp.ll
index cb052f653dea7..fe17cd353e02e 100644
--- a/llvm/test/Transforms/SCCP/strictfp-phis-fcmp.ll
+++ b/llvm/test/Transforms/SCCP/strictfp-phis-fcmp.ll
@@ -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]]

diff  --git a/llvm/test/Transforms/SCCP/strictfp-phis-fcmps.ll b/llvm/test/Transforms/SCCP/strictfp-phis-fcmps.ll
index 1c90082262cbd..61e20ef70b0ec 100644
--- a/llvm/test/Transforms/SCCP/strictfp-phis-fcmps.ll
+++ b/llvm/test/Transforms/SCCP/strictfp-phis-fcmps.ll
@@ -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]]

diff  --git a/llvm/test/Transforms/SCCP/widening.ll b/llvm/test/Transforms/SCCP/widening.ll
index db4f62fd1938d..eb75442585f77 100644
--- a/llvm/test/Transforms/SCCP/widening.ll
+++ b/llvm/test/Transforms/SCCP/widening.ll
@@ -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


        


More information about the llvm-commits mailing list