Skip to content

[DFAJumpThreading] Don't thread switch without multiple successors #71060

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 2, 2023

Conversation

XChy
Copy link
Member

@XChy XChy commented Nov 2, 2023

Fixes #56882.
Fixes #60254.

When switch has only one successor, it make no sense to thread it. And computing the cost of it brings div-by-zero exception. We prevent it in this patch.

@XChy XChy requested review from nikic and dancgr November 2, 2023 13:25
@llvmbot
Copy link
Member

llvmbot commented Nov 2, 2023

@llvm/pr-subscribers-llvm-transforms

Author: XChy (XChy)

Changes

Fixes #56882.
Fixes #60254.

When switch has only one successor, it make no sense to thread it. And computing the cost of it brings div-by-zero exception. We prevent it in this patch.


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp (+6)
  • (added) llvm/test/Transforms/DFAJumpThreading/single_succ_switch.ll (+43)
diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
index f2efe60bdf886a2..66407a3b2d504a2 100644
--- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
@@ -728,6 +728,10 @@ struct TransformDFA {
     CodeMetrics Metrics;
     SwitchInst *Switch = SwitchPaths->getSwitchInst();
 
+    // Don't thread switch without multiple successors.
+    if (Switch->getNumSuccessors() <= 1)
+      return false;
+
     // Note that DuplicateBlockMap is not being used as intended here. It is
     // just being used to ensure (BB, State) pairs are only counted once.
     DuplicateBlockMap DuplicateMap;
@@ -805,6 +809,8 @@ struct TransformDFA {
       // using binary search, hence the LogBase2().
       unsigned CondBranches =
           APInt(32, Switch->getNumSuccessors()).ceilLogBase2();
+      assert(CondBranches > 0 &&
+             "The threaded switch must have multiple branches");
       DuplicationCost = Metrics.NumInsts / CondBranches;
     } else {
       // Compared with jump tables, the DFA optimizer removes an indirect branch
diff --git a/llvm/test/Transforms/DFAJumpThreading/single_succ_switch.ll b/llvm/test/Transforms/DFAJumpThreading/single_succ_switch.ll
new file mode 100644
index 000000000000000..00500a7a2598d85
--- /dev/null
+++ b/llvm/test/Transforms/DFAJumpThreading/single_succ_switch.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -passes=dfa-jump-threading %s | FileCheck %s
+
+define void @pr60254() {
+; CHECK-LABEL: define void @pr60254() {
+; CHECK-NEXT:  entry_1:
+; CHECK-NEXT:    br label [[BB_2:%.*]]
+; CHECK:       bb_2:
+; CHECK-NEXT:    [[PTR_I32_25_0:%.*]] = phi i32 [ 0, [[BB_4:%.*]] ], [ 0, [[BB_2]] ], [ 0, [[ENTRY_1:%.*]] ]
+; CHECK-NEXT:    switch i32 [[PTR_I32_25_0]], label [[BB_2]] [
+; CHECK-NEXT:    ]
+; CHECK:       bb_4:
+; CHECK-NEXT:    br label [[BB_2]]
+;
+entry_1:
+  br label %bb_2
+
+bb_2:                                             ; preds = %bb_4, %bb_2, %entry_1
+  %ptr_i32_25.0 = phi i32 [ 0, %bb_4 ], [ 0, %bb_2 ], [ 0, %entry_1 ]
+  switch i32 %ptr_i32_25.0, label %bb_2 [
+  ]
+
+bb_4:                                             ; No predecessors!
+  br label %bb_2
+}
+
+define void @pr56882() {
+; CHECK-LABEL: define void @pr56882() {
+; CHECK-NEXT:  entry_1:
+; CHECK-NEXT:    br label [[BB_2:%.*]]
+; CHECK:       bb_2:
+; CHECK-NEXT:    [[PTR_I64_16_0:%.*]] = phi i64 [ -1317805584074026212, [[ENTRY_1:%.*]] ], [ -158622699357888703, [[BB_2]] ]
+; CHECK-NEXT:    switch i64 [[PTR_I64_16_0]], label [[BB_2]] [
+; CHECK-NEXT:    ]
+;
+entry_1:
+  br label %bb_2
+
+bb_2:                                             ; preds = %bb_2, %entry_1
+  %ptr_i64_16.0 = phi i64 [ -1317805584074026212, %entry_1 ], [ -158622699357888703, %bb_2 ]
+  switch i64 %ptr_i64_16.0, label %bb_2 [
+  ]
+}

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@XChy XChy merged commit 2fba469 into llvm:main Nov 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash in DFAJumpThreading [DFAJumpThreading] Simple IR tests crashes on DFAJumpThreading pass
3 participants