Bug type: crash
Component: VectorCombine
Bug location: llvm/lib/Transforms/Vectorize/VectorCombine.cpp: eraseInstruction
Issue title: [VectorCombine] SIGSEGV at O3
Labels: crash-on-valid
llvm::vectorcombine
Reported by: dtcxzyw

```
; bin/opt -passes=vector-combine reduced.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 void @wombat() {
bb:
  %alloca.sroa.0.32.vec.expand = shufflevector <4 x double> zeroinitializer, <4 x double> zeroinitializer, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 0, i32 1, i32 2, i32 3>
  %alloca.sroa.0.32.vecblend = shufflevector <8 x double> zeroinitializer, <8 x double> %alloca.sroa.0.32.vec.expand, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
  %0 = fadd <8 x double> zeroinitializer, %alloca.sroa.0.32.vec.expand
  %arg112.sroa.0.0.vecblend.i.i = shufflevector <8 x double> %0, <8 x double> %alloca.sroa.0.32.vecblend, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
  ret void
}
```
```
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/opt -passes=vector-combine reduced.ll -S
1.      Running pass "function(vector-combine)" on module "reduced.ll"
2.      Running pass "vector-combine" on function "wombat"
 #0 0x00007f8472c306e2 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.22.0git+0x2306e2)
 #1 0x00007f8472c2ccaf llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.22.0git+0x22ccaf)
 #2 0x00007f8472c2cdfc SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007f8472645330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
 #4 0x00007f846c15a554 llvm::Value::assertModuleIsMaterializedImpl() const (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.22.0git+0x35a554)
 #5 0x00007f846cda0400 llvm::RecursivelyDeleteTriviallyDeadInstructions(llvm::SmallVectorImpl<llvm::WeakTrackingVH>&, llvm::TargetLibraryInfo const*, llvm::MemorySSAUpdater*, std::function<void (llvm::Value*)>) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMTransformUtils.so.22.0git+0x1a0400)
 #6 0x00007f846cda0ab0 llvm::RecursivelyDeleteTriviallyDeadInstructions(llvm::Value*, llvm::TargetLibraryInfo const*, llvm::MemorySSAUpdater*, std::function<void (llvm::Value*)>) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMTransformUtils.so.22.0git+0x1a0ab0)
 #7 0x00007f846ea7e821 (anonymous namespace)::VectorCombine::eraseInstruction(llvm::Instruction&) VectorCombine.cpp:0:0
 #8 0x00007f846ea9e05a llvm::VectorCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.22.0git+0x29e05a)
 #9 0x00007f846f4f0eb5 llvm::detail::PassModel<llvm::Function, llvm::VectorCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMPasses.so.22.0git+0xf0eb5)
#10 0x00007f846c127929 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+0x327929)
#11 0x00007f8471cdd2c5 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+0xdd2c5)
#12 0x00007f846c126792 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.22.0git+0x326792)
#13 0x00007f8472e02145 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+0x20145)
#14 0x00007f846c12495d 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+0x32495d)
#15 0x00007f8472e0f125 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+0x2d125)
#16 0x00007f8472e1a599 optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.22.0git+0x38599)
#17 0x00007f847262a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#18 0x00007f847262a28b call_init ./csu/../csu/libc-start.c:128:20
#19 0x00007f847262a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#20 0x000061f20c4f8095 _start (bin/opt+0x1095)
Segmentation fault (core dumped)
```
Reported by @alexfh https://github.com/llvm/llvm-project/pull/151142#issuecomment-3225370210



Fix patch:
commit abd2dc90c039cf8b3907f096743fc69380c8b245
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Wed Aug 27 22:28:02 2025 +0800

    [VectorCombine] Avoid double deletion in `eraseInstruction` (#155621)
    
    Consider the following pattern:
    ```
    C = op A B
    D = op C
    E = op D, C
    ```
    As `E` is dead, we call `eraseInstruction(E)` and see if its operands
    become dead. `RecursivelyDeleteTriviallyDeadInstructions(D)` also erases
    `C`, which causes a UAF crash in the subsequent call
    `RecursivelyDeleteTriviallyDeadInstructions(C)`.
    
    This patch also adds deleted ops into the visit list to avoid double
    deletion.
    
    Closes https://github.com/llvm/llvm-project/issues/155543.

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 56a08b843871..c88ed95de294 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -173,15 +173,16 @@ private:
     // further folds that were hindered by OneUse limits.
     SmallPtrSet<Value *, 4> Visited;
     for (Value *Op : Ops) {
-      if (Visited.insert(Op).second) {
+      if (!Visited.contains(Op)) {
         if (auto *OpI = dyn_cast<Instruction>(Op)) {
           if (RecursivelyDeleteTriviallyDeadInstructions(
-                  OpI, nullptr, nullptr, [this](Value *V) {
+                  OpI, nullptr, nullptr, [&](Value *V) {
                     if (auto *I = dyn_cast<Instruction>(V)) {
                       LLVM_DEBUG(dbgs() << "VC: Erased: " << *I << '\n');
                       Worklist.remove(I);
                       if (I == NextInst)
                         NextInst = NextInst->getNextNode();
+                      Visited.insert(I);
                     }
                   }))
             continue;


Regression tests:
file: llvm/test/Transforms/VectorCombine/X86/pr155543.ll
commands: opt < %s -passes=vector-combine -S -mtriple=x86_64--
tests: test_name: <module>
test_body: 
; Make sure we don't double delete a dead instruction.

define void @pr155543() {
;
  %shuffle1 = shufflevector <4 x double> poison, <4 x double> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 0, i32 1, i32 2, i32 3>
  %shuffle2 = shufflevector <8 x double> poison, <8 x double> %shuffle1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
  %fadd = fadd <8 x double> %shuffle1, zeroinitializer
  %dead = shufflevector <8 x double> %fadd, <8 x double> %shuffle2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
  ret void
}