Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::isGatherShuffledSingleRegisterEntry
Issue title: clang crashes on valid code at -O2 on x86_64-linux-gnu: Assertion `TEPtr->UserTreeIndices.size() == 1 && "Expected only single user of a gather node."' failed 
Labels: llvm:SLPVectorizer
crash-on-valid
Reported by: zhendongsu

It appears to be a recent regression as it doesn't reproduce with 19.1.0 and earlier. 

Compiler Explorer: https://godbolt.org/z/a1W3c5ard

```
[523] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git df8b785838a2db01b4d056e603f7317209accefb)
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
[524] % 
[524] % clangtk -O2 small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:12559: std::optional<llvm::TargetTransformInfo::ShuffleKind> llvm::slpvectorizer::BoUpSLP::isGatherShuffledSingleRegisterEntry(const llvm::slpvectorizer::BoUpSLP::TreeEntry*, llvm::ArrayRef<llvm::Value*>, llvm::MutableArrayRef<int>, llvm::SmallVectorImpl<const llvm::slpvectorizer::BoUpSLP::TreeEntry*>&, unsigned int, bool): Assertion `TEPtr->UserTreeIndices.size() == 1 && "Expected only single user of a gather node."' 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-20 -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/20241020-clangtk-m64-O2-build-231331/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20241020-clangtk-m64-O2-build-231331/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/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 -O2 -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-572b89.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,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<O2>,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 0x0000560576c8b9af llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x43f29af)
 #1 0x0000560576c89184 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f4623c27420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f462365e00b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f462363d859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f462363d729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f462363d729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f462364efd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000560578707edc 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-20+0x5e6eedc)
 #9 0x0000560578708cd8 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-20+0x5e6fcd8)
#10 0x000056057870a6f3 llvm::InstructionCost llvm::slpvectorizer::BoUpSLP::processBuildVector<llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator, llvm::InstructionCost, llvm::TargetTransformInfo, llvm::ArrayRef<llvm::Value*>, llvm::slpvectorizer::BoUpSLP, llvm::SmallPtrSetImpl<llvm::Value*>>(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::Type*, llvm::TargetTransformInfo&, llvm::ArrayRef<llvm::Value*>&, llvm::slpvectorizer::BoUpSLP&, llvm::SmallPtrSetImpl<llvm::Value*>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e716f3)
#11 0x000056057870cde7 llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e73de7)
#12 0x0000560578745f69 llvm::slpvectorizer::BoUpSLP::getTreeCost(llvm::ArrayRef<llvm::Value*>) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5eacf69)
#13 0x000056057874b57b (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#14 0x000056057874eb79 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5eb5b79)
#15 0x000056057875349b llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#16 0x0000560578757d50 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5ebed50)
#17 0x000056057875e590 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
#18 0x000056057875f263 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5ec6263)
#19 0x00005605781e0e66 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-20+0x5947e66)
#20 0x0000560576614891 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d7b891)
#21 0x000056057410e656 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-20+0x1875656)
#22 0x00005605766131fd llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d7a1fd)
#23 0x000056057410d196 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-20+0x1874196)
#24 0x0000560576612c31 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d79c31)
#25 0x0000560576f44dd3 (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
#26 0x0000560576f483a8 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, 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-20+0x46af3a8)
#27 0x000056057764462c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4dab62c)
#28 0x000056057951629c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6c7d29c)
#29 0x0000560577644a48 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4daba48)
#30 0x000056057790d3d9 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x50743d9)
#31 0x00005605778895ce clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4ff05ce)
#32 0x00005605779f9f26 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5160f26)
#33 0x0000560573cd1fe5 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1438fe5)
#34 0x0000560573cc9afa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#35 0x0000560573cce52e clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x143552e)
#36 0x0000560573bba67b main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x132167b)
#37 0x00007f462363f083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#38 0x0000560573cc958e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x143058e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git df8b785838a2db01b4d056e603f7317209accefb)
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-d99d4e.c
clangtk: note: diagnostic msg: /tmp/small-d99d4e.sh
clangtk: note: diagnostic msg: 

********************
[525] % 
[525] % cat small.c
int a, b, c, d, e, f;
int main() {
  for (f = 0; f < 4; f++) {
    d &= (((a > 0) != b) != c) && b;
    for (b = 0; b < 1; b++)
      if (e)
        break;
  }
  return 0;
}
```




Fix patch:
commit 9e03920cbf946e7ba282e99213707643a23ae5fb
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Oct 21 08:57:36 2024 -0700

    [SLP]Ignore root gather node, when searching for reuses
    
    Root gather/buildvector node should be ignored when SLP vectorizer tries
    to find matching gather nodes, vectorized earlier. This node is
    definitely the last one in the pipeline and it does not have users. It
    may cause the compiler crash
    
    Fixes #113143

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 1098bf578d2d..a11e3f3815cb 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -12466,7 +12466,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
     // Build a list of tree entries where V is used.
     SmallPtrSet<const TreeEntry *, 4> VToTEs;
     for (const TreeEntry *TEPtr : ValueToGatherNodes.find(V)->second) {
-      if (TEPtr == TE)
+      if (TEPtr == TE || TEPtr->Idx == 0)
         continue;
       assert(any_of(TEPtr->Scalars,
                     [&](Value *V) { return GatheredScalars.contains(V); }) &&


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/root-gather-reused-scalar.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define void @test(ptr %a, i32 %0, i32 %1, i1 %cmp1) {
entry:
  %2 = load i32, ptr %a, align 4
  %tobool10.not = icmp eq i32 %0, 0
  %cmp4.3 = icmp ne i32 %1, 0
  %3 = and i1 %cmp4.3, %tobool10.not
  %cmp2.2 = xor i1 %tobool10.not, true
  %conv3.2 = zext i1 %cmp2.2 to i32
  %cmp4.2 = icmp ne i32 %2, %conv3.2
  %cmp2.1 = xor i1 %cmp1, true
  %conv3.1 = zext i1 %cmp2.1 to i32
  %cmp4.1 = icmp ne i32 %2, %conv3.1
  %4 = select i1 %3, i1 %cmp4.2, i1 false
  %5 = select i1 %4, i1 %cmp4.1, i1 false
  %and.3 = zext i1 %5 to i32
  store i32 %and.3, ptr %a, align 4
  ret void
}