Bug type: crash
Component: SimplifyCFG
Bug location: llvm/lib/Transforms/Utils/SimplifyCFG.cpp: SimplifyCFGOpt::turnSwitchRangeIntoICmp
Issue title: [SimplifyCFG] SIGSEGV at O3
Labels: crash-on-valid
llvm:transforms
generated by fuzzer
Reported by: dtcxzyw

Reproducer: https://godbolt.org/z/j4r194cah
```
; bin/opt -passes=simplifycfg<switch-range-to-icmp> test.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define fastcc i32 @func_285(i1 %tobool271) {
entry:
  br label %if.then102

if.then102:                                       ; preds = %if.then102, %if.then102, %entry
  switch i1 %tobool271, label %default.unreachable [
    i1 false, label %if.then102
    i1 true, label %if.then102
  ]

default.unreachable:                              ; preds = %if.then102
  %conv257.1.lcssa = phi i32 [ 0, %if.then102 ]
  ret i32 %conv257.1.lcssa
}
```
```
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 "function(simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>)" on module "<source>"
2.	Running pass "simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>" on function "func_285"
 #0 0x0000000005975828 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5975828)
 #1 0x00000000059726d4 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x000073a3a8042520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x0000000004c4aabb (anonymous namespace)::SimplifyCFGOpt::simplifySwitch(llvm::SwitchInst*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&) SimplifyCFG.cpp:0:0
 #4 0x0000000004c52343 llvm::simplifyCFG(llvm::BasicBlock*, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&, llvm::ArrayRef<llvm::WeakVH>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c52343)
 #5 0x000000000484f644 iterativelySimplifyCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
 #6 0x0000000004850594 simplifyFunctionCFGImpl(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
 #7 0x0000000004851715 simplifyFunctionCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
 #8 0x000000000485185a llvm::SimplifyCFGPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x485185a)
 #9 0x00000000016dcc3e llvm::detail::PassModel<llvm::Function, llvm::SimplifyCFGPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x16dcc3e)
#10 0x000000000574f081 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x574f081)
#11 0x0000000000efc57e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xefc57e)
#12 0x000000000574d6fa llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x574d6fa)
#13 0x000000000097bade llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x97bade)
#14 0x000000000574d0b1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x574d0b1)
#15 0x0000000000985c7a 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+0x985c7a)
#16 0x0000000000979ef1 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x979ef1)
#17 0x000073a3a8029d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#18 0x000073a3a8029e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#19 0x0000000000971305 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x971305)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
Not sure if https://github.com/llvm/llvm-project/pull/165105 helps.


Comments: author: dtcxzyw
body: Trigger another assertion after https://github.com/llvm/llvm-project/pull/165105.

```
opt: /home/dtcxzyw/WorkSpace/Projects/compilers/llvm-project/llvm/include/llvm/Support/Casting.h:109: static bool llvm::isa_impl_cl<To, const From*>::doit(const From*) [with To = llvm::PHINode; From = llvm::Instruction]: Assertion `Val && "isa<> used on a null pointer"' failed.
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: bin/opt -passes=simplifycfg<switch-range-to-icmp> test.ll -S
1.      Running pass "function(simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>)" on module "test.ll"
2.      Running pass "simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>" on function "func_285"
 #0 0x00007d665e653992 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.22.0git+0x253992)
 #1 0x00007d665e64ff5f llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.22.0git+0x24ff5f)
 #2 0x00007d665e6500ac SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007d665e045330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
 #4 0x00007d665e09eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007d665e09eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007d665e09eb2c pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007d665e04527e raise ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007d665e0288ff abort ./stdlib/abort.c:81:7
 #9 0x00007d665e02881b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007d665e03b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#11 0x00007d66586bbe1c (anonymous namespace)::SimplifyCFGOpt::turnSwitchRangeIntoICmp(llvm::SwitchInst*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&) SimplifyCFG.cpp:0:0
#12 0x00007d66586e2df1 (anonymous namespace)::SimplifyCFGOpt::simplifySwitch(llvm::SwitchInst*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&) SimplifyCFG.cpp:0:0
#13 0x00007d66586eaf15 llvm::simplifyCFG(llvm::BasicBlock*, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&, llvm::ArrayRef<llvm::WeakVH>) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMTransformUtils.so.22.0git+0x2eaf15)
#14 0x00007d66591c31ed iterativelySimplifyCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#15 0x00007d66591c41b9 simplifyFunctionCFGImpl(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#16 0x00007d66591c4ba5 simplifyFunctionCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#17 0x00007d66591c4d00 llvm::SimplifyCFGPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMScalarOpts.so.22.0git+0x3c4d00)
#18 0x00007d665b1a7195 llvm::detail::PassModel<llvm::Function, llvm::SimplifyCFGPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libPolly.so.22.0git+0x1a7195)
#19 0x00007d6657925189 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.22.0git+0x325189)
#20 0x00007d665d8dd385 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.22.0git+0xdd385)
#21 0x00007d6657923612 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.22.0git+0x323612)
#22 0x00007d665e8e1375 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.22.0git+0x20375)
#23 0x00007d6657923e3d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.22.0git+0x323e3d)
#24 0x00007d665e8ee3c1 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) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.22.0git+0x2d3c1)
#25 0x00007d665e8f94e5 optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.22.0git+0x384e5)
#26 0x00007d665e02a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#27 0x00007d665e02a28b call_init ./csu/../csu/libc-start.c:128:20
#28 0x00007d665e02a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#29 0x0000620ebe031095 _start (bin/opt+0x1095)
Aborted (core dumped)
```
author: dtcxzyw
body: https://github.com/llvm/llvm-project/blob/b258f5c2527f895dfa98921b61482978aba407e0/llvm/lib/Transforms/Utils/SimplifyCFG.cpp#L5978-L5988

`removeIncomingValue` erases the PHI node. So there is a use-after-free in the next iteration. Unfortunately my machine is down while building LLVM :(


Fix patch:
commit 56777e7da2cb30f72a3ddc9861a2fbe3b9adbc6b
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Oct 31 10:30:29 2025 +0800

    [SimplifyCFG] Avoid use-after-free when removing incoming values from PHI nodes (#165744)
    
    `PHINode::removeIncomingValue` removes itself when there are no incoming
    edges. Then we cannot use it to retrieve the next instruction.
    
    Closes https://github.com/llvm/llvm-project/issues/165301.

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index b03fb6213d61..7f6d779687e9 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -5977,14 +5977,14 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
   }
 
   // Prune obsolete incoming values off the successors' PHI nodes.
-  for (auto BBI = Dest->begin(); isa<PHINode>(BBI); ++BBI) {
+  for (auto &PHI : make_early_inc_range(Dest->phis())) {
     unsigned PreviousEdges = Cases->size();
     if (Dest == SI->getDefaultDest())
       ++PreviousEdges;
     for (unsigned I = 0, E = PreviousEdges - 1; I != E; ++I)
-      cast<PHINode>(BBI)->removeIncomingValue(SI->getParent());
+      PHI.removeIncomingValue(SI->getParent());
   }
-  for (auto BBI = OtherDest->begin(); isa<PHINode>(BBI); ++BBI) {
+  for (auto &PHI : make_early_inc_range(OtherDest->phis())) {
     unsigned PreviousEdges = OtherCases->size();
     if (OtherDest == SI->getDefaultDest())
       ++PreviousEdges;
@@ -5993,7 +5993,7 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
     if (NewBI->isUnconditional())
       ++E;
     for (unsigned I = 0; I != E; ++I)
-      cast<PHINode>(BBI)->removeIncomingValue(SI->getParent());
+      PHI.removeIncomingValue(SI->getParent());
   }
 
   // Clean up the default block - it may have phis or other instructions before


Regression tests:
file: llvm/test/Transforms/SimplifyCFG/pr165301.ll
commands: opt -S -passes="simplifycfg<switch-range-to-icmp>" < %s
tests: test_name: <module>
test_body: 
; Make sure there's no use after free when removing incoming values from PHI nodes

define i32 @pr165301(i1 %cond) {
;
entry:
  br label %switchbb

switchbb:
  switch i1 %cond, label %default [
  i1 false, label %switchbb
  i1 true, label %switchbb
  ]

default:
  %phi.lcssa = phi i32 [ 0, %switchbb ]
  ret i32 %phi.lcssa
}