Bug type: crash
Component: SimplifyCFG
Bug location: llvm/lib/Transforms/Utils/SimplifyCFG.cpp: SimplifyCFGOpt::turnSwitchRangeIntoICmp
Issue title: [SimplifyCFG] PHINode should have one entry for each predecessor of its parent basic block!
Labels: crash-on-valid
llvm:transforms
Reported by: dtcxzyw

Reproducer: https://godbolt.org/z/aP7nrYf57
```
; bin/opt -passes="simplifycfg<switch-range-to-icmp>" reduced.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64-unknown-linux"

define i32 @r535_gr_promote_ctx(i1 %0) {
  switch i1 %0, label %5 [
    i1 false, label %2
    i1 true, label %2
  ]

2:
  br i1 %0, label %5, label %3

3:
  br label %5

5:
  %6 = phi i32 [ 0, %1 ], [ 0, %2 ], [ 1, %3 ]
  ret i32 %6
}
```
```
PHINode should have one entry for each predecessor of its parent basic block!
  %4 = phi i32 [ %spec.select, %1 ], [ 0, %1 ], [ %spec.select, %2 ]
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=simplifycfg<switch-range-to-icmp> <source>
1.	Running pass "verify" on module "<source>"
 #0 0x0000000005915ae8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5915ae8)
 #1 0x0000000005912994 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x00007062ae242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007062ae2969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007062ae242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007062ae2287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00000000008322ef llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x000000000584be91 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x584be91)
 #8 0x000000000573c998 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x573c998)
 #9 0x00000000009766ce llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x9766ce)
#10 0x00000000056f9da1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x56f9da1)
#11 0x000000000098080a llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x98080a)
#12 0x0000000000974a57 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x974a57)
#13 0x00007062ae229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x00007062ae229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x000000000096bb65 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x96bb65)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
Originally reported by @nathanchance :https://github.com/llvm/llvm-project/pull/161000#issuecomment-3382948552



Fix patch:
commit e9205ca8cf4235647c3ec2a1946850751ce4e1c8
Author: dianqk <dianqk@dianqk.net>
Date:   Fri Oct 10 06:44:00 2025 +0800

    [SimplifyCFG] Remove all incoming values from OtherDest if OtherDest is unreachable (#162677)
    
    Fixes #162585.
    
    #161000 changed `br i1 true, label %if, label %else` to `br label %if`,
    so we should remove one more incoming value.

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 155fcc50bdeb..9ac3be1e1206 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -5959,7 +5959,11 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
     unsigned PreviousEdges = OtherCases->size();
     if (OtherDest == SI->getDefaultDest())
       ++PreviousEdges;
-    for (unsigned I = 0, E = PreviousEdges - 1; I != E; ++I)
+    unsigned E = PreviousEdges - 1;
+    // Remove all incoming values from OtherDest if OtherDest is unreachable.
+    if (NewBI->isUnconditional())
+      ++E;
+    for (unsigned I = 0; I != E; ++I)
       cast<PHINode>(BBI)->removeIncomingValue(SI->getParent());
   }
 


Regression tests:
file: llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
commands: opt %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S
tests: test_name: else_will_be_unreachable
test_body: define i32 @else_will_be_unreachable(i1 %arg) {
entry:
  switch i1 %arg, label %else [
    i1 false, label %if
    i1 true, label %if
  ]

if:                                               ; preds = %entry, %entry
  br i1 %arg, label %else, label %bb

bb:                                               ; preds = %if
  br label %else

else:                                             ; preds = %bb, %if, %entry
  %i = phi i32 [ 0, %entry ], [ 0, %if ], [ 1, %bb ]
  ret i32 %i
}