Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: tryToReduce
Issue title: [SLPVectorizer] Assertion `(I->use_empty() || all_of(I->uses(), [&](Use &U) { return isDeleted( cast<Instruction>(U.getUser())); })) && "trying to erase instruction with users."' failed.
Labels: llvm:SLPVectorizer
crash-on-valid
Reported by: dtcxzyw

Reproducer: https://godbolt.org/z/b8cz56M9z
```
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 i32 @test(i1 %cond) {
entry:
  br label %for.end14.i.i.i.us.i

for.end14.i.i.i.us.i:
  %.promoted10921110.i.i.i.us.i = phi i32 [ %inc229.1.2.i.i.i.us.us.12.i, %for.end14.i.i.i.us.i ], [ 0, %entry ]
  %.promoted1106.i.i.i.us.i = phi i32 [ %0, %for.end14.i.i.i.us.i ], [ 0, %entry ]
  %g_276.promoted956960.i.i.i.us.i = phi i32 [ %4, %for.end14.i.i.i.us.i ], [ 0, %entry ]
  %0 = or i32 1, 0
  %inc229.1974.i.i.i.us.us.8.i = or i32 0, 0
  %inc229.1974.i.i.i.us.us.9.i = or i32 0, 0
  %inc229.1.2.i.i.i.us.us.9.i = or i32 %.promoted10921110.i.i.i.us.i, 0
  %inc229.1974.i.i.i.us.us.12.i = or i32 %.promoted1106.i.i.i.us.i, 0
  %inc229.1.2.i.i.i.us.us.12.i = or i32 1, 0
  %1 = xor i32 %inc229.1.2.i.i.i.us.us.9.i, %inc229.1974.i.i.i.us.us.12.i
  %2 = xor i32 %1, %inc229.1974.i.i.i.us.us.9.i
  %3 = xor i32 %2, %inc229.1974.i.i.i.us.us.8.i
  %4 = xor i32 %3, %inc229.1.2.i.i.i.us.us.12.i
  br i1 %cond, label %exit, label %for.end14.i.i.i.us.i

exit:
  ret i32 %4
}
```
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:2720: void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands(llvm::ArrayRef<U*>) [with T = llvm::Instruction]: Assertion `(I->use_empty() || all_of(I->uses(), [&](Use &U) { return isDeleted( cast<Instruction>(U.getUser())); })) && "trying to erase instruction with users."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "test"
 #0 0x000000000507e338 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x507e338)
 #1 0x000000000507bcec SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f54a0842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007f54a08969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007f54a0842476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007f54a08287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00007f54a082871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x00007f54a0839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000004102d6f void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands<llvm::Instruction>(llvm::ArrayRef<llvm::Instruction*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4102d6f)
 #9 0x000000000415dea2 llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::MapVector<llvm::Value*, llvm::SmallVector<llvm::Instruction*, 2u>, llvm::DenseMap<llvm::Value*, unsigned int, llvm::DenseMapInfo<llvm::Value*, void>, llvm::detail::DenseMapPair<llvm::Value*, unsigned int>>, llvm::SmallVector<std::pair<llvm::Value*, llvm::SmallVector<llvm::Instruction*, 2u>>, 0u>> const&, llvm::Instruction*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x415dea2)
#10 0x0000000004167819 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#11 0x000000000416a302 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x416a302)
#12 0x000000000416ebb8 llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x416ebb8)
#13 0x0000000004172da1 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4172da1)
#14 0x00000000041796b1 llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (.part.0) SLPVectorizer.cpp:0:0
#15 0x000000000417a33b llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x417a33b)
#16 0x0000000002f33c8e llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2f33c8e)
#17 0x0000000004e81158 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e81158)
#18 0x0000000000e15bde 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+0xe15bde)
#19 0x0000000004e7fb7e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7fb7e)
#20 0x0000000000e1538e 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+0xe1538e)
#21 0x0000000004e7f5b0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7f5b0)
#22 0x0000000000904102 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) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x904102)
#23 0x00000000008f6f8c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f6f8c)
#24 0x00007f54a0829d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#25 0x00007f54a0829e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#26 0x00000000008eea5e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8eea5e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
llvm version: e379094328e49731a606304f7e3559d4f1fa96f9

Comments: author: alexey-bataev
body: Fixed in 4dede756f25b153a81ea883ef84064f5a1eaaec2

Fix patch:
commit 4dede756f25b153a81ea883ef84064f5a1eaaec2
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Wed Oct 2 05:50:20 2024 -0700

    [SLP]Transform nodes before building externally used values
    
    transformNodes function may create new vector nodes, so the reduced
    values might be vectorized later. Need to build the list of the
    externally used values after the transformNodes() function call to avoid
    compiler crash.
    
    Fixe #110787

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 15e798bd6c98..ce1e5753c0c8 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -18848,6 +18848,7 @@ public:
             ++SameValuesCounter.try_emplace(OrigV).first->second;
           }
         }
+        V.transformNodes();
         SmallPtrSet<Value *, 4> VLScalars(VL.begin(), VL.end());
         // Gather externally used values.
         SmallPtrSet<Value *, 4> Visited;
@@ -18877,7 +18878,6 @@ public:
         for (Value *RdxVal : VL)
           if (RequiredExtract.contains(RdxVal))
             LocalExternallyUsedValues[RdxVal];
-        V.transformNodes();
         V.buildExternalUses(LocalExternallyUsedValues);
 
         V.computeMinimumValueSizes();


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/reduced-val-vectorized-in-transform.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define i32 @test(i1 %cond) {
entry:
  br label %bb

bb:                                               ; preds = %bb, %entry
  %p1 = phi i32 [ %or92, %bb ], [ 0, %entry ]
  %p2 = phi i32 [ %0, %bb ], [ 0, %entry ]
  %p3 = phi i32 [ %4, %bb ], [ 0, %entry ]
  %0 = or i32 1, 0
  %or8.i = or i32 0, 0
  %or9.i = or i32 0, 0
  %or91 = or i32 %p1, 0
  %or12.i = or i32 %p2, 0
  %or92 = or i32 1, 0
  %1 = xor i32 %or91, %or12.i
  %2 = xor i32 %1, %or9.i
  %3 = xor i32 %2, %or8.i
  %4 = xor i32 %3, %or92
  br i1 %cond, label %exit, label %bb

exit:                                             ; preds = %bb
  ret i32 %4
}