Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::transformNodes
Issue title: Assertion `I->use_empty() && "trying to erase instruction with users."' failed.
Labels: llvm:SLPVectorizer
crash
Reported by: TatyanaDoubts

To reproduce run opt with the test below (-passes=slp-vectorizer -slp-threshold=-99999)

[reduced-stripped.ll.zip](https://github.com/user-attachments/files/24473473/reduced-stripped.ll.zip)

Reproducer: https://godbolt.org/z/c8rcjzPdr

Stack dump:
```
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer -slp-threshold=-99999 <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "wombat"
 #0 0x0000000005a7f2e8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5a7f2e8)
 #1 0x0000000005a7c194 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x000072441c042520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000072441c0969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000072441c042476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000072441c0287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000072441c02871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000072441c039e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x000000000379becf llvm::slpvectorizer::BoUpSLP::~BoUpSLP() (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x379becf)
 #9 0x0000000003896946 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
#10 0x00000000038973cb llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x38973cb)
#11 0x000000000304364e 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+0x304364e)
#12 0x0000000005859c61 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5859c61)
#13 0x0000000000f1ba3e 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+0xf1ba3e)
#14 0x000000000585821a llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x585821a)
#15 0x000000000097ee5e 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+0x97ee5e)
#16 0x0000000005857bd1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5857bd1)
#17 0x0000000000989110 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+0x989110)
#18 0x000000000097d038 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x97d038)
#19 0x000072441c029d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#20 0x000072441c029e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#21 0x0000000000973a35 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x973a35)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Comments: author: EugeneZelenko
body: @TatyanaDoubts: If you plan to file more issues in future, it'll be good idea to request triage role ([examples](https://github.com/llvm/llvm-project/issues/?q=is%3Aissue%20label%3Ainfra%3Acommit-access-request%20Triage)), so you'll be able to label issues yourself, preferably at creation.


Fix patch:
commit 9fb45c5959fdbf1f63babd1f32ad298cab9e27af
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Jan 8 06:13:44 2026 -0800

    [SLP]Do not generate extractelement subnodes with the same indeces
    
    The compiler should not generate subvectors with the same extractelement
    instructions, it may cause a crash and leads to inefficient
    vectorization.
    
    Fixes #174773

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index cc78d0189066..a5117f09a778 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -13445,6 +13445,7 @@ void BoUpSLP::transformNodes() {
       // insertvector instructions.
       unsigned StartIdx = 0;
       unsigned End = VL.size();
+      SmallBitVector Processed(End);
       for (unsigned VF = getFloorFullVectorNumberOfElements(
                *TTI, VL.front()->getType(), VL.size() - 1);
            VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
@@ -13457,7 +13458,7 @@ void BoUpSLP::transformNodes() {
           ArrayRef<Value *> Slice = VL.slice(Cnt, VF);
           // If any instruction is vectorized already - do not try again.
           // Reuse the existing node, if it fully matches the slice.
-          if (isVectorized(Slice.front()) &&
+          if ((Processed.test(Cnt) || isVectorized(Slice.front())) &&
               !getSameValuesTreeEntry(Slice.front(), Slice, /*SameVF=*/true))
             continue;
           // Constant already handled effectively - skip.
@@ -13543,6 +13544,7 @@ void BoUpSLP::transformNodes() {
           continue;
         auto AddCombinedNode = [&](unsigned Idx, unsigned Cnt, unsigned Sz) {
           E.CombinedEntriesWithIndices.emplace_back(Idx, Cnt);
+          Processed.set(Cnt, Cnt + Sz);
           if (StartIdx == Cnt)
             StartIdx = Cnt + Sz;
           if (End == Cnt + Sz)


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/extractelements-subnodes-same-index.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 -mattr=+avx < %s
tests: test_name: <module>
test_body: 
define i32 @test() {
;
bb:
  %call = call i32 @llvm.ctpop.i32(i32 0)
  %call1 = call i32 @llvm.ctpop.i32(i32 0)
  %load = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 32), align 4
  store i32 %load, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 32), align 4
  %or = or i32 %call, %call1
  %call2 = call i32 @llvm.ctpop.i32(i32 0)
  %or3 = or i32 %or, %call2
  %call4 = call i32 @llvm.ctpop.i32(i32 0)
  %load9 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 28), align 4
  store i32 %load9, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 28), align 4
  %or5 = or i32 %or3, %call4
  %call6 = call i32 @llvm.ctpop.i32(i32 0)
  %or7 = or i32 %or5, %call6
  %call8 = call i32 @llvm.ctpop.i32(i32 0)
  %load14 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 28), align 4
  store i32 %load14, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 28), align 4
  %load15 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 24), align 4
  store i32 %load15, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 24), align 4
  %or10 = or i32 %or7, %call8
  %call11 = call i32 @llvm.ctpop.i32(i32 %load)
  %or12 = or i32 %or10, %call11
  %call13 = call i32 @llvm.ctpop.i32(i32 0)
  %load20 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 24), align 4
  store i32 %load20, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 24), align 4
  %load21 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 20), align 4
  store i32 %load21, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 20), align 4
  %or16 = or i32 %or12, %call13
  %call17 = call i32 @llvm.ctpop.i32(i32 %load9)
  %or18 = or i32 %or16, %call17
  %call19 = call i32 @llvm.ctpop.i32(i32 %load14)
  %load26 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 20), align 4
  store i32 %load26, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 20), align 4
  %load27 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 16), align 4
  store i32 %load27, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 16), align 4
  %or22 = or i32 %or18, %call19
  %call23 = call i32 @llvm.ctpop.i32(i32 %load15)
  %or24 = or i32 %or22, %call23
  %call25 = call i32 @llvm.ctpop.i32(i32 %load20)
  %load32 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 16), align 4
  store i32 %load32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 16), align 4
  %load33 = load i32, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 12), align 4
  store i32 %load33, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) null, i64 12), align 4
  %or28 = or i32 %or24, %call25
  %call29 = call i32 @llvm.ctpop.i32(i32 %load21)
  %or30 = or i32 %or28, %call29
  %call31 = call i32 @llvm.ctpop.i32(i32 %load26)
  %or34 = or i32 %or30, %call31
  %call35 = call i32 @llvm.ctpop.i32(i32 %load27)
  %or36 = or i32 %or34, %call35
  %call37 = call i32 @llvm.ctpop.i32(i32 %load32)
  %or38 = or i32 %or36, %call37
  %call39 = call i32 @llvm.ctpop.i32(i32 %load33)
  %or40 = or i32 %or38, %call39
  %call41 = call i32 @llvm.ctpop.i32(i32 0)
  %or42 = or i32 %or40, %call41
  %call43 = call i32 @llvm.ctpop.i32(i32 0)
  %or44 = or i32 %or42, %call43
  %call45 = call i32 @llvm.ctpop.i32(i32 0)
  %or46 = or i32 %or44, %call45
  %call47 = call i32 @llvm.ctpop.i32(i32 0)
  %or48 = or i32 %or46, %call47
  %call49 = call i32 @llvm.ctpop.i32(i32 0)
  %or50 = or i32 %or48, %call49
  %call51 = call i32 @llvm.ctpop.i32(i32 0)
  %or52 = or i32 %or50, %call51
  %call53 = call i32 @llvm.ctpop.i32(i32 0)
  %or54 = or i32 %or52, %call53
  ret i32 %or54
}

declare i32 @llvm.ctpop.i32(i32)