Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::isGatherShuffledSingleRegisterEntry
Issue title: clang crashes at -O{s,2,3} on x86_64-linux-gnu: Assertion `idx < size()' failed
Labels: llvm:SLPVectorizer
crash
Reported by: zhendongsu

It appears to be a recent regression as it doesn't reproduce with 20.1.0.

Compiler Explorer: https://godbolt.org/z/nKW8o5f8a

```
[516] % clangtk -v
clang version 21.0.0git (https://github.com/llvm/llvm-project.git 842785adf7349f07a91320d49ff8a10971e04409)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[517] % 
[517] % clangtk -O3 small.c
clang-21: /local/suz-local/software/clangbuild/llvm-project/llvm/include/llvm/ADT/SmallVector.h:291: T& llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::operator[](llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::size_type) [with T = const llvm::slpvectorizer::BoUpSLP::TreeEntry*; <template-parameter-1-2> = void; llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::reference = const llvm::slpvectorizer::BoUpSLP::TreeEntry*&; llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::size_type = long unsigned int]: Assertion `idx < size()' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-21 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/20250402-clangtk-m64-O3-build-141643/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20250402-clangtk-m64-O3-build-141643/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/21 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-1ffa5d.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,chr,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O3>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "slp-vectorizer" on function "main"
 #0 0x000055aa281b4bff llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x459bbff)
 #1 0x000055aa281b23b4 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x00007f3259793420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f32591ca00b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f32591a9859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f32591a9729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f32591a9729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f32591bafd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x000055aa29cd9e82 llvm::slpvectorizer::BoUpSLP::isGatherShuffledSingleRegisterEntry(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::MutableArrayRef<int>, llvm::SmallVectorImpl<llvm::slpvectorizer::BoUpSLP::TreeEntry const*>&, unsigned int, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x60c0e82)
 #9 0x000055aa29cda9f8 llvm::slpvectorizer::BoUpSLP::isGatherShuffledEntry(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallVectorImpl<int>&, llvm::SmallVectorImpl<llvm::SmallVector<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, 6u>>&, unsigned int, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x60c19f8)
#10 0x000055aa29cdb803 llvm::slpvectorizer::BoUpSLP::findReusedOrderedScalars(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x60c2803)
#11 0x000055aa29d11537 llvm::slpvectorizer::BoUpSLP::getReorderingData(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x60f8537)
#12 0x000055aa29d15fc6 llvm::slpvectorizer::BoUpSLP::reorderBottomToTop(bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x60fcfc6)
#13 0x000055aa29d236d8 llvm::SLPVectorizerPass::tryToVectorizeList(llvm::ArrayRef<llvm::Value*>, llvm::slpvectorizer::BoUpSLP&, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x610a6d8)
#14 0x000055aa29d28bdd bool tryToVectorizeSequence<llvm::Value>(llvm::SmallVectorImpl<llvm::Value*>&, llvm::function_ref<bool (llvm::Value*, llvm::Value*)>, llvm::function_ref<bool (llvm::Value*, llvm::Value*)>, llvm::function_ref<bool (llvm::ArrayRef<llvm::Value*>, bool)>, bool, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#15 0x000055aa29d2a5d1 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x61115d1)
#16 0x000055aa29d3268e 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
#17 0x000055aa29d33253 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x611a253)
#18 0x000055aa2979da56 llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x5b84a56)
#19 0x000055aa27b29009 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x3f10009)
#20 0x000055aa253f1e66 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x17d8e66)
#21 0x000055aa27b27882 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x3f0e882)
#22 0x000055aa253ef826 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x17d6826)
#23 0x000055aa27b272a1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x3f0e2a1)
#24 0x000055aa28473351 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#25 0x000055aa28476c41 clang::emitBackendOutput(clang::CompilerInstance&, clang::CodeGenOptions&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x485dc41)
#26 0x000055aa28b92391 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x4f79391)
#27 0x000055aa2a56658c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x694d58c)
#28 0x000055aa28b927c8 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x4f797c8)
#29 0x000055aa28e8fcb9 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x5276cb9)
#30 0x000055aa28e0f98e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x51f698e)
#31 0x000055aa28f86ae6 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x536dae6)
#32 0x000055aa24f83afd cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x136aafd)
#33 0x000055aa24f7b08a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#34 0x000055aa24f7f312 clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x1366312)
#35 0x000055aa24e62f8b main (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x1249f8b)
#36 0x00007f32591ab083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#37 0x000055aa24f7ab1e _start (/local/suz-local/software/local/clang-trunk/bin/clang-21+0x1361b1e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 21.0.0git (https://github.com/llvm/llvm-project.git 842785adf7349f07a91320d49ff8a10971e04409)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clangtk: note: diagnostic msg: /tmp/small-a83f08.c
clangtk: note: diagnostic msg: /tmp/small-a83f08.sh
clangtk: note: diagnostic msg: 

********************
[518] % 
[518] % cat small.c
int printf(const char *, ...);
int a, b, c, d;
int main() {
  int g = 1, h = 0, i, j;
k:
  if (g) {
    int l = a, n;
  m:
    n = d;
    if (n)
      goto o;
    j = l;
  }
  int p = a / ~b;
  if (g)
  q:
    b = a;
  c = p;
  int r = g ? 0 : ~i, s = ~h;
  if (g) {
    r = j;
    if (b && 0 <= i) {
      if (h) {
        g = 0;
        goto m;
      }
      i = a = -a;
      if (a)
        printf("0");
    t:
      j = 0;
      if (d)
        goto k;
    }
  }
  h = r;
  j = s;
  if (a) {
  o:
    if (a && i)
      goto t;
    goto q;
  }
  return 0;
}
```

Comments: author: dtcxzyw
body: Reduced reproducer: https://godbolt.org/z/E7zsza3bT

Fix patch:
commit 843ef77dc22afd1923b891acd4c46c8f8c8c93ae
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Wed Apr 2 11:44:36 2025 -0700

    [SLP]Update mapping between values and their matching entries upon selection
    
    Need to update the mapping between gathered values and their matching
    entries, if the list of the entries is updated and only some of them are
    selected for final shuffling.
    
    Fixes #134085

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 838e952c024c..b82a66ca3b88 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -14335,7 +14335,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
   // single vector. If we have 2 different sets, we're in situation where we
   // have a permutation of 2 input vectors.
   SmallVector<SmallPtrSet<const TreeEntry *, 4>> UsedTEs;
-  DenseMap<Value *, int> UsedValuesEntry;
+  SmallDenseMap<Value *, int> UsedValuesEntry;
   SmallPtrSet<const Value *, 16> VisitedValue;
   auto CheckAndUseSameNode = [&](const TreeEntry *TEPtr) {
     // The node is reused - exit.
@@ -14552,6 +14552,8 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
     // No perfect match, just shuffle, so choose the first tree node from the
     // tree.
     Entries.push_back(FirstEntries.front());
+    // Update mapping between values and corresponding tree entries.
+    for_each(UsedValuesEntry, [&](auto &P) { P.second = 0; });
     VF = FirstEntries.front()->getVectorFactor();
   } else {
     // Try to find nodes with the same vector factor.
@@ -14596,6 +14598,18 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
     } else {
       VF = Entries.front()->getVectorFactor();
     }
+    SmallVector<SmallPtrSet<Value *, 8>> ValuesToEntries;
+    for (const TreeEntry *E : Entries)
+      ValuesToEntries.emplace_back().insert(E->Scalars.begin(),
+                                            E->Scalars.end());
+    // Update mapping between values and corresponding tree entries.
+    for_each(UsedValuesEntry, [&](auto &P) {
+      for (unsigned Idx : seq<unsigned>(ValuesToEntries.size()))
+        if (ValuesToEntries[Idx].contains(P.first)) {
+          P.second = Idx;
+          break;
+        }
+    });
   }
 
   bool IsSplatOrUndefs = isSplat(VL) || all_of(VL, IsaPred<UndefValue>);


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/matched-nodes-updated.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: <module>
test_body: 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 @main(i32 %s.0) {
entry:
  br label %k

k:                                                ; preds = %t, %entry
  %.pre = phi i32 [ 0, %entry ], [ %.pre4053, %t ]
  br label %o

if.end3:                                          ; No predecessors!
  br label %if.end6

if.end6:                                          ; preds = %o, %if.end3
  %.pre43 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %0 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %1 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %h.4 = phi i32 [ 0, %if.end3 ], [ %h.6, %o ]
  %i.4 = phi i32 [ 0, %if.end3 ], [ %i.7, %o ]
  %j.4 = phi i32 [ 0, %if.end3 ], [ %j.5, %o ]
  %l.4 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %not8 = xor i32 %i.4, 0
  %not9 = xor i32 %h.4, 0
  br i1 false, label %if.end24, label %if.then11

if.then11:                                        ; preds = %if.end6
  br label %if.end24

if.then18:                                        ; No predecessors!
  br label %t

t:                                                ; preds = %o, %if.then18
  %.pre40 = phi i32 [ %.pre4053, %o ], [ 0, %if.then18 ]
  %i.5 = phi i32 [ 0, %o ], [ 0, %if.then18 ]
  %l.5 = phi i32 [ %l.7, %o ], [ 0, %if.then18 ]
  %r.2 = phi i32 [ %r.4, %o ], [ 0, %if.then18 ]
  %s.2 = phi i32 [ %s.4, %o ], [ 0, %if.then18 ]
  br i1 false, label %if.end24, label %k

if.end24:                                         ; preds = %t, %if.then11, %if.end6
  %.pre4050 = phi i32 [ 0, %if.then11 ], [ 0, %if.end6 ], [ %.pre40, %t ]
  %.pre42 = phi i32 [ 0, %if.then11 ], [ %.pre43, %if.end6 ], [ %.pre40, %t ]
  %2 = phi i32 [ 0, %if.then11 ], [ %0, %if.end6 ], [ %.pre40, %t ]
  %3 = phi i32 [ 0, %if.then11 ], [ %1, %if.end6 ], [ %.pre40, %t ]
  %i.6 = phi i32 [ %i.4, %if.then11 ], [ %i.7, %if.end6 ], [ %i.5, %t ]
  %l.6 = phi i32 [ 0, %if.then11 ], [ %l.4, %if.end6 ], [ %l.5, %t ]
  %r.3 = phi i32 [ %j.4, %if.then11 ], [ %not8, %if.end6 ], [ %r.2, %t ]
  %s.3 = phi i32 [ 0, %if.then11 ], [ %not9, %if.end6 ], [ %s.2, %t ]
  br label %o

o:                                                ; preds = %if.end24, %k
  %.pre4053 = phi i32 [ 0, %k ], [ %.pre4050, %if.end24 ]
  %.pre46 = phi i32 [ 0, %k ], [ %.pre42, %if.end24 ]
  %4 = phi i32 [ 0, %k ], [ %2, %if.end24 ]
  %5 = phi i32 [ 0, %k ], [ %3, %if.end24 ]
  %h.6 = phi i32 [ 0, %k ], [ %r.3, %if.end24 ]
  %i.7 = phi i32 [ 0, %k ], [ %i.6, %if.end24 ]
  %j.5 = phi i32 [ 0, %k ], [ %s.3, %if.end24 ]
  %l.7 = phi i32 [ %.pre, %k ], [ %l.6, %if.end24 ]
  %r.4 = phi i32 [ 0, %k ], [ %r.3, %if.end24 ]
  %s.4 = phi i32 [ %s.0, %k ], [ %s.3, %if.end24 ]
  br i1 false, label %t, label %if.end6

; uselistorder directives
  uselistorder i32 %.pre4053, { 1, 0 }
  uselistorder i32 %i.7, { 1, 0 }
}