[llvm] [JumpThreading] Fix bugs of simplifying BB with unreachable predecessor (PR #68576)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 9 04:07:27 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

<details>
<summary>Changes</summary>

Resolve #<!-- -->68529.
JumpThreading calls TryToSimplifyUncondBranchFromEmptyBlock without checking/removing unreachable pred, which results in incorrectly redirecting value from unreachable predecessor.
This patch adds check for it.

---
Full diff: https://github.com/llvm/llvm-project/pull/68576.diff


3 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/JumpThreading.cpp (+8) 
- (modified) llvm/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll (+35) 
- (modified) llvm/test/Transforms/JumpThreading/unreachable-loops.ll (+6-2) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index ed69f1938ec7921..fc10243cff19964 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -368,6 +368,13 @@ bool JumpThreadingPass::runImpl(Function &F_, FunctionAnalysisManager *FAM_,
         continue;
       }
 
+      auto PredsAreReachable = [&Unreachable](BasicBlock *BB) -> bool {
+        for (auto *Pred : predecessors(BB))
+          if (Unreachable.count(Pred))
+            return false;
+        return true;
+      };
+
       // processBlock doesn't thread BBs with unconditional TIs. However, if BB
       // is "almost empty", we attempt to merge BB with its sole successor.
       auto *BI = dyn_cast<BranchInst>(BB.getTerminator());
@@ -379,6 +386,7 @@ bool JumpThreadingPass::runImpl(Function &F_, FunctionAnalysisManager *FAM_,
             // Don't alter Loop headers and latches to ensure another pass can
             // detect and transform nested loops later.
             !LoopHeaders.count(&BB) && !LoopHeaders.count(Succ) &&
+            PredsAreReachable(&BB) &&
             TryToSimplifyUncondBranchFromEmptyBlock(&BB, DTU.get())) {
           RemoveRedundantDbgInstrs(Succ);
           // BB is valid for cleanup here because we passed in DTU. F remains
diff --git a/llvm/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll b/llvm/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll
index 2a9765233ec1043..e8fa399ff8a6d99 100644
--- a/llvm/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll
+++ b/llvm/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll
@@ -27,3 +27,38 @@ exit1:
 exit2:
   ret void
 }
+
+define i32 @bar(i32 noundef %a) {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    br i1 [[DOTNOT]], label [[END:%.*]], label [[ELSE:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[B:%.*]] = and i32 undef, 65535
+; CHECK-NEXT:    br label [[B2:%.*]]
+; CHECK:       dead:
+; CHECK-NEXT:    br label [[B2]]
+; CHECK:       B2:
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[DOT0:%.*]] = phi i32 [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[B2]] ]
+; CHECK-NEXT:    ret i32 [[DOT0]]
+;
+entry:
+  %.not = icmp eq i32 %a, 0
+  br i1 %.not, label %end, label %else
+
+  else:                                                ; preds = %1
+  %b = and i32 undef, 65535
+  br label %B2
+
+dead:                                                ; No predecessors!
+  br label %B2
+
+B2:                                                ; preds = %2, %4
+  br label %end
+
+end:                                                ; preds = %5, %1
+  %.0 = phi i32 [ %a, %entry ], [ %b, %B2 ]
+  ret i32 %.0
+}
diff --git a/llvm/test/Transforms/JumpThreading/unreachable-loops.ll b/llvm/test/Transforms/JumpThreading/unreachable-loops.ll
index 8d649761700a90c..7e1dcfb3e4c78a9 100644
--- a/llvm/test/Transforms/JumpThreading/unreachable-loops.ll
+++ b/llvm/test/Transforms/JumpThreading/unreachable-loops.ll
@@ -15,9 +15,11 @@ define void @unreachable_single_bb_loop() {
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i32 [[TMP]], 1
 ; CHECK-NEXT:    switch i1 [[TMP4]], label [[BB2:%.*]] [
-; CHECK-NEXT:    i1 false, label [[BB8]]
+; CHECK-NEXT:    i1 false, label [[BB7:%.*]]
 ; CHECK-NEXT:    i1 true, label [[BB8]]
 ; CHECK-NEXT:    ]
+; CHECK:       bb7:
+; CHECK-NEXT:    br label [[BB8]]
 ; CHECK:       bb8:
 ; CHECK-NEXT:    ret void
 ;
@@ -57,9 +59,11 @@ define void @unreachable_multi_bbs_loop() {
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i32 [[TMP]], 1
 ; CHECK-NEXT:    switch i1 [[TMP4]], label [[BB3:%.*]] [
-; CHECK-NEXT:    i1 false, label [[BB8]]
+; CHECK-NEXT:    i1 false, label [[BB7:%.*]]
 ; CHECK-NEXT:    i1 true, label [[BB8]]
 ; CHECK-NEXT:    ]
+; CHECK:       bb7:
+; CHECK-NEXT:    br label [[BB8]]
 ; CHECK:       bb8:
 ; CHECK-NEXT:    ret void
 ;

``````````

</details>


https://github.com/llvm/llvm-project/pull/68576


More information about the llvm-commits mailing list