commit b9d3da8c8d277a7fc2223c659122bb377a0e54e0
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Aug 26 04:31:44 2024 -0700

    [SLP]Fix PR105904: the root node might be a gather node without user for reductions.

    Before checking the user components of the gather/buildvector nodes,
    need to check if the node has users at all. Root nodes might not have
    users, if it is a node for the reduction.

    Fixes https://github.com/llvm/llvm-project/issues/105904

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 949579772b94..def73e8d0c0d 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3011,7 +3011,8 @@ private:
     }

     bool isOperandGatherNode(const EdgeInfo &UserEI) const {
-      return isGather() && UserTreeIndices.front().EdgeIdx == UserEI.EdgeIdx &&
+      return isGather() && (Idx > 0 || !UserTreeIndices.empty()) &&
+             UserTreeIndices.front().EdgeIdx == UserEI.EdgeIdx &&
              UserTreeIndices.front().UserTE == UserEI.UserTE;
     }

opt -S --passes=slp-vectorizer -mtriple=riscv64-unknown-linux-gnu -mattr=+v,+zvl512b < %s

define void @test(ptr %c) {
entry:
  %arrayidx8.5.3 = getelementptr i8, ptr %c, i64 222
  %0 = load i8, ptr %arrayidx8.5.3, align 1
  %arrayidx8.7.3 = getelementptr i8, ptr %c, i64 228
  %1 = load i8, ptr %arrayidx8.7.3, align 1
  %arrayidx8.434 = getelementptr i8, ptr %c, i64 276
  %2 = load i8, ptr %arrayidx8.434, align 1
  %arrayidx8.1.4 = getelementptr i8, ptr %c, i64 279
  %3 = load i8, ptr %arrayidx8.1.4, align 1
  %arrayidx8.2.4 = getelementptr i8, ptr %c, i64 282
  %4 = load i8, ptr %arrayidx8.2.4, align 1
  %arrayidx8.3.4 = getelementptr i8, ptr %c, i64 285
  %5 = load i8, ptr %arrayidx8.3.4, align 1
  %arrayidx8.4.4 = getelementptr i8, ptr %c, i64 288
  %6 = load i8, ptr %arrayidx8.4.4, align 1
  %7 = load i8, ptr %c, align 1
  %8 = load i8, ptr %c, align 1
  %arrayidx8.536 = getelementptr i8, ptr %c, i64 345
  %9 = load i8, ptr %arrayidx8.536, align 1
  %arrayidx8.1.5 = getelementptr i8, ptr %c, i64 348
  %10 = load i8, ptr %arrayidx8.1.5, align 1
  %arrayidx8.2.5 = getelementptr i8, ptr %c, i64 351
  %11 = load i8, ptr %arrayidx8.2.5, align 1
  %arrayidx8.3.5 = getelementptr i8, ptr %c, i64 354
  %12 = load i8, ptr %arrayidx8.3.5, align 1
  %arrayidx8.4.5 = getelementptr i8, ptr %c, i64 357
  %13 = load i8, ptr %arrayidx8.4.5, align 1
  %arrayidx8.5.5 = getelementptr i8, ptr %c, i64 360
  %14 = load i8, ptr %arrayidx8.5.5, align 1
  %arrayidx8.6.5 = getelementptr i8, ptr %c, i64 363
  %15 = load i8, ptr %arrayidx8.6.5, align 1
  br label %for.cond

for.cond:                                         ; preds = %for.cond, %entry
  %a.promoted2226 = phi i8 [ 0, %entry ], [ %or18.6.5, %for.cond ]
  %or18.7.3 = or i8 %0, %1
  %or18.435 = or i8 %or18.7.3, %2
  %or18.1.4 = or i8 %or18.435, %3
  %or18.2.4 = or i8 %or18.1.4, %4
  %or18.3.4 = or i8 %or18.2.4, %5
  %or18.4.4 = or i8 %or18.3.4, %6
  %or18.5.4 = or i8 %or18.4.4, %7
  %or18.6.4 = or i8 %or18.5.4, %8
  %or18.537 = or i8 %or18.6.4, %9
  %or18.1.5 = or i8 %or18.537, %10
  %or18.2.5 = or i8 %or18.1.5, %11
  %or18.3.5 = or i8 %or18.2.5, %12
  %or18.4.5 = or i8 %or18.3.5, %13
  %or18.5.5 = or i8 %or18.4.5, %14
  %or18.6.5 = or i8 %or18.5.5, %15
  br label %for.cond
}

[SLP Vectorizer] Assertion `!empty()' failed.

Testcase:
```llvm ir
 ModuleID = 'reduced.bc'
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @b(ptr %c) #0 {
entry:
  %arrayidx8.5.3 = getelementptr i8, ptr %c, i64 222
  %0 = load i8, ptr %arrayidx8.5.3, align 1
  %arrayidx8.7.3 = getelementptr i8, ptr %c, i64 228
  %1 = load i8, ptr %arrayidx8.7.3, align 1
  %arrayidx8.434 = getelementptr i8, ptr %c, i64 276
  %2 = load i8, ptr %arrayidx8.434, align 1
  %arrayidx8.1.4 = getelementptr i8, ptr %c, i64 279
  %3 = load i8, ptr %arrayidx8.1.4, align 1
  %arrayidx8.2.4 = getelementptr i8, ptr %c, i64 282
  %4 = load i8, ptr %arrayidx8.2.4, align 1
  %arrayidx8.3.4 = getelementptr i8, ptr %c, i64 285
  %5 = load i8, ptr %arrayidx8.3.4, align 1
  %arrayidx8.4.4 = getelementptr i8, ptr %c, i64 288
  %6 = load i8, ptr %arrayidx8.4.4, align 1
  %7 = load i8, ptr %c, align 1
  %8 = load i8, ptr %c, align 1
  %arrayidx8.536 = getelementptr i8, ptr %c, i64 345
  %9 = load i8, ptr %arrayidx8.536, align 1
  %arrayidx8.1.5 = getelementptr i8, ptr %c, i64 348
  %10 = load i8, ptr %arrayidx8.1.5, align 1
  %arrayidx8.2.5 = getelementptr i8, ptr %c, i64 351
  %11 = load i8, ptr %arrayidx8.2.5, align 1
  %arrayidx8.3.5 = getelementptr i8, ptr %c, i64 354
  %12 = load i8, ptr %arrayidx8.3.5, align 1
  %arrayidx8.4.5 = getelementptr i8, ptr %c, i64 357
  %13 = load i8, ptr %arrayidx8.4.5, align 1
  %arrayidx8.5.5 = getelementptr i8, ptr %c, i64 360
  %14 = load i8, ptr %arrayidx8.5.5, align 1
  %arrayidx8.6.5 = getelementptr i8, ptr %c, i64 363
  %15 = load i8, ptr %arrayidx8.6.5, align 1
  br label %for.cond

for.cond:                                         ; preds = %for.cond, %entry
  %a.promoted2226 = phi i8 [ 0, %entry ], [ %or18.6.5, %for.cond ]
  %or18.7.3 = or i8 %0, %1
  %or18.435 = or i8 %or18.7.3, %2
  %or18.1.4 = or i8 %or18.435, %3
  %or18.2.4 = or i8 %or18.1.4, %4
  %or18.3.4 = or i8 %or18.2.4, %5
  %or18.4.4 = or i8 %or18.3.4, %6
  %or18.5.4 = or i8 %or18.4.4, %7
  %or18.6.4 = or i8 %or18.5.4, %8
  %or18.537 = or i8 %or18.6.4, %9
  %or18.1.5 = or i8 %or18.537, %10
  %or18.2.5 = or i8 %or18.1.5, %11
  %or18.3.5 = or i8 %or18.2.5, %12
  %or18.4.5 = or i8 %or18.3.5, %13
  %or18.5.5 = or i8 %or18.4.5, %14
  %or18.6.5 = or i8 %or18.5.5, %15
  br label %for.cond
}

attributes #0 = { "target-features"="+64bit,+relax,+xsifivecflushdlone,+zicsr,+zve32x,+zve64x,+zvl1024b,+zvl128b,+zvl256b,+zvl32b,+zvl512b,+zvl64b,-a,-b,-c,-d,-e,-experimental-smctr,-experimental-smmpm,-experimental-smnpm,-experimental-ssctr,-experimental-ssnpm,-experimental-sspm,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-m,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-ztso,-zvbb,-zvbc,-zve32f,-zve64d,-zve64f,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl16384b,-zvl2048b,-zvl32768b,-zvl4096b,-zvl65536b,-zvl8192b" }
```
Godbolt: https://godbolt.org/z/Thhajqn9q

Command/backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt --passes=slp-vectorizer -S reduced.ll
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/include/llvm/ADT/SmallVector.h:317: const T& llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::front() const [with T = llvm::slpvectorizer::BoUpSLP::EdgeInfo; <template-parameter-1-2> = void; llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::const_reference = const llvm::slpvectorizer::BoUpSLP::EdgeInfo&]: Assertion `!empty()' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt --passes=slp-vectorizer -S reduced.ll
1.      Running pass "function(slp-vectorizer)" on module "reduced.ll"
2.      Running pass "slp-vectorizer" on function "b"
 #0 0x00005da37ad02b80 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x300eb80)
 #1 0x00005da37acfff9f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x300bf9f)
 #2 0x00005da37ad000f5 SignalHandler(int) Signals.cpp:0:0
 #3 0x0000733cc0242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x0000733cc02969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x0000733cc02969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x0000733cc02969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x0000733cc0242476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x0000733cc02287f3 abort ./stdlib/abort.c:81:7
 #9 0x0000733cc022871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x0000733cc0239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00005da379da2beb llvm::slpvectorizer::BoUpSLP::vectorizeOperand(llvm::slpvectorizer::BoUpSLP::TreeEntry*, unsigned int, bool) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20aebeb)
#12 0x00005da379d9e086 llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::slpvectorizer::BoUpSLP::TreeEntry*, bool) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20aa086)
#13 0x00005da379da2372 llvm::slpvectorizer::BoUpSLP::vectorizeOperand(llvm::slpvectorizer::BoUpSLP::TreeEntry*, unsigned int, bool) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20ae372)
#14 0x00005da379d9db47 llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::slpvectorizer::BoUpSLP::TreeEntry*, bool) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20a9b47)
#15 0x00005da379d9c510 llvm::slpvectorizer::BoUpSLP::createBuildVector(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::Type*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20a8510)
#16 0x00005da379d9cf7b llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::slpvectorizer::BoUpSLP::TreeEntry*, bool) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20a8f7b)
#17 0x00005da379da62cf 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::SmallVectorImpl<std::pair<llvm::Value*, llvm::Value*>>&, llvm::Instruction*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20b22cf)
#18 0x00005da379db2bd5 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#19 0x00005da379db5599 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20c1599)
#20 0x00005da379db9a68 llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20c5a68)
#21 0x00005da379dbd75c llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20c975c)
#22 0x00005da379dc41b0 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
#23 0x00005da379dc4da2 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20d0da2)
#24 0x00005da378b51cf6 llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5dcf6)
#25 0x00005da37ab0e94f llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1a94f)
#26 0x00005da378b544f6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe604f6)
#27 0x00005da37ab0d6cb llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e196cb)
#28 0x00005da378b50796 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5c796)
#29 0x00005da37ab0b70d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1770d)
#30 0x00005da37837ae56 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) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x686e56)
#31 0x00005da37836cbe1 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x678be1)
#32 0x0000733cc0229d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#33 0x0000733cc0229e40 call_init ./csu/../csu/libc-start.c:128:20
#34 0x0000733cc0229e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#35 0x00005da378362f95 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x66ef95)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Found via fuzzer