Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::getEntryCost
Issue title: [SLPVectorizer] Assertion `OpIdx < Operands.size() && "Off bounds"' failed.
Labels: llvm:SLPVectorizer
crash-on-valid
Reported by: dtcxzyw

Reproducer: https://godbolt.org/z/6GbP5f7qa
```
; bin/opt -passes=slp-vectorizer reduced.ll -S
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 i1 @main() {
entry:
  %cond.i112.18.i308.i.i = shl i32 0, 0
  %cond.i112.19.i315.i.i = shl i32 0, 0
  %and.19.i316.i.i = and i32 %cond.i112.18.i308.i.i, %cond.i112.19.i315.i.i
  %cond.i112.20.i322.i.i = shl i32 0, 0
  %and.20.i323.i.i = and i32 %and.19.i316.i.i, %cond.i112.20.i322.i.i
  %cond.i112.21.i329.i.i = shl i32 0, 0
  %and.21.i330.i.i = and i32 %and.20.i323.i.i, %cond.i112.21.i329.i.i
  %0 = trunc i64 0 to i32
  %conv85.22.i333.i.i = or i32 0, %0
  %cmp3.i.22.i334.i.i = icmp ugt i32 %conv85.22.i333.i.i, 0
  %shl.i111.22.i335.i.i = select i1 %cmp3.i.22.i334.i.i, i32 0, i32 0
  %cond.i112.22.i336.i.i = shl i32 %conv85.22.i333.i.i, %shl.i111.22.i335.i.i
  %and.22.i337.i.i = and i32 %and.21.i330.i.i, %cond.i112.22.i336.i.i
  %1 = trunc i64 0 to i32
  %conv85.23.i340.i.i = or i32 0, %1
  %cmp3.i.23.i341.i.i = icmp ugt i32 %conv85.23.i340.i.i, 0
  %shl.i111.23.i342.i.i = select i1 %cmp3.i.23.i341.i.i, i32 0, i32 0
  %cond.i112.23.i343.i.i = shl i32 %conv85.23.i340.i.i, %shl.i111.23.i342.i.i
  %and.23.i344.i.i = and i32 %and.22.i337.i.i, %cond.i112.23.i343.i.i
  %2 = trunc i64 0 to i32
  %conv85.24.i347.i.i = or i32 0, %2
  %cmp3.i.24.i348.i.i = icmp ugt i32 %conv85.24.i347.i.i, 0
  %shl.i111.24.i349.i.i = select i1 %cmp3.i.24.i348.i.i, i32 0, i32 0
  %cond.i112.24.i350.i.i = shl i32 %conv85.24.i347.i.i, %shl.i111.24.i349.i.i
  %and.24.i351.i.i = and i32 %and.23.i344.i.i, %cond.i112.24.i350.i.i
  %3 = trunc i64 0 to i32
  %conv85.25.i354.i.i = or i32 0, %3
  %cmp3.i.25.i355.i.i = icmp ugt i32 %conv85.25.i354.i.i, 0
  %shl.i111.25.i356.i.i = select i1 %cmp3.i.25.i355.i.i, i32 0, i32 0
  %cond.i112.25.i357.i.i = shl i32 %conv85.25.i354.i.i, %shl.i111.25.i356.i.i
  %and.25.i358.i.i = and i32 %and.24.i351.i.i, %cond.i112.25.i357.i.i
  %conv109.i.i = trunc i32 %and.25.i358.i.i to i8
  %cmp.i.i54.i = icmp eq i8 %conv109.i.i, 0
  ret i1 %cmp.i.i54.i
}
```
```
opt: /home/dtcxzyw/WorkSpace/Projects/compilers/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:3247: llvm::slpvectorizer::BoUpSLP::ValueList& llvm::slpvectorizer::BoUpSLP::TreeEntry::getOperand(unsigned int): Assertion `OpIdx < Operands.size() && "Off bounds"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/opt -passes=slp-vectorizer reduced.ll
1.      Running pass "function(slp-vectorizer)" on module "reduced.ll"
2.      Running pass "slp-vectorizer" on function "main"
 #0 0x000075e591a13b52 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.20.0git+0x213b52)
 #1 0x000075e591a10a1f llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.20.0git+0x210a1f)
 #2 0x000075e591a10b65 SignalHandler(int) Signals.cpp:0:0
 #3 0x000075e591442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000075e5914969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x000075e5914969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x000075e5914969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x000075e591442476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x000075e5914287f3 abort ./stdlib/abort.c:81:7
 #9 0x000075e59142871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x000075e591439e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000075e58c574c14 (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x174c14)
#12 0x000075e58c5bcafe llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1bcafe)
#13 0x000075e58c5d0eed llvm::slpvectorizer::BoUpSLP::getTreeCost(llvm::ArrayRef<llvm::Value*>) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1d0eed)
#14 0x000075e58c5d68cc (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#15 0x000075e58c5d997a llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1d997a)
#16 0x000075e58c5ddf28 llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1ddf28)
#17 0x000075e58c5de0cb bool llvm::SLPVectorizerPass::vectorizeCmpInsts<std::reverse_iterator<llvm::CmpInst* const*>>(llvm::iterator_range<std::reverse_iterator<llvm::CmpInst* const*>>, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1de0cb)
#18 0x000075e58c5e2299 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1e2299)
#19 0x000075e58c5e8c0f llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1e8c0f)
#20 0x000075e58c5e9876 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.20.0git+0x1e9876)
#21 0x000075e58ced5195 llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMPasses.so.20.0git+0xd5195)
#22 0x000075e58a15de5d llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.20.0git+0x35de5d)
#23 0x000075e5904d9d05 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.20.0git+0xd9d05)
#24 0x000075e58a15bf96 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.20.0git+0x35bf96)
#25 0x000075e5904da6c5 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.20.0git+0xda6c5)
#26 0x000075e58a15cb1a llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.20.0git+0x35cb1a)
#27 0x000075e591c041c1 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) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.20.0git+0x2d1c1)
#28 0x000075e591c0f944 optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.20.0git+0x38944)
#29 0x000075e591429d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#30 0x000075e591429e40 call_init ./csu/../csu/libc-start.c:128:20
#31 0x000075e591429e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#32 0x00005b421cc0e095 _start (bin/opt+0x1095)
Aborted (core dumped)
```

llvm version: 2b84ef06ac55ac8de3c210d059ec3a3c96666a90


Fix patch:
commit af6354634d2cec14570108ee038ca4b18cf6856a
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Fri Sep 27 03:55:17 2024 -0700

    [SLP]Look for vector user when estimating the cost
    
    Need to find the first vector node user, not the very first user node at
    all. The very first user might be a gather, vectorized as clustered,
    which may cause compiler crash.
    
    Fixes https://github.com/llvm/llvm-project/issues/110193

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 48a8627ab63e..dee0b7e1f437 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -10340,13 +10340,16 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
         InstructionCost VecCost = VectorCost(CommonCost);
         // Check if the current node must be resized, if the parent node is not
         // resized.
-        if (!UnaryInstruction::isCast(E->getOpcode()) && E->Idx != 0 &&
+        if (It != MinBWs.end() && !UnaryInstruction::isCast(E->getOpcode()) &&
+            E->Idx != 0 &&
             (E->getOpcode() != Instruction::Load ||
              !E->UserTreeIndices.empty())) {
-          const EdgeInfo &EI = E->UserTreeIndices.front();
-          if ((EI.UserTE->getOpcode() != Instruction::Select ||
-               EI.EdgeIdx != 0) &&
-              It != MinBWs.end()) {
+          const EdgeInfo &EI =
+              *find_if(E->UserTreeIndices, [](const EdgeInfo &EI) {
+                return !EI.UserTE->isGather() || EI.EdgeIdx != UINT_MAX;
+              });
+          if (EI.UserTE->getOpcode() != Instruction::Select ||
+              EI.EdgeIdx != 0) {
             auto UserBWIt = MinBWs.find(EI.UserTE);
             Type *UserScalarTy =
                 EI.UserTE->getOperand(EI.EdgeIdx).front()->getType();


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/minbw-multiused-from-gather.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define i1 @test() {
entry:
  %c18.i308.i.i = shl i32 0, 0
  %c19.i315.i.i = shl i32 0, 0
  %and.19.i316.i.i = and i32 %c18.i308.i.i, %c19.i315.i.i
  %c20.i322.i.i = shl i32 0, 0
  %and.20.i323.i.i = and i32 %and.19.i316.i.i, %c20.i322.i.i
  %c21.i329.i.i = shl i32 0, 0
  %and.21.i330.i.i = and i32 %and.20.i323.i.i, %c21.i329.i.i
  %0 = trunc i64 0 to i32
  %conv85.22.i333.i.i = or i32 0, %0
  %cmp3.i.22.i334.i.i = icmp ugt i32 %conv85.22.i333.i.i, 0
  %shl.i111.22.i335.i.i = select i1 %cmp3.i.22.i334.i.i, i32 0, i32 0
  %c22.i336.i.i = shl i32 %conv85.22.i333.i.i, %shl.i111.22.i335.i.i
  %and.22.i337.i.i = and i32 %and.21.i330.i.i, %c22.i336.i.i
  %1 = trunc i64 0 to i32
  %conv85.23.i340.i.i = or i32 0, %1
  %cmp3.i.23.i341.i.i = icmp ugt i32 %conv85.23.i340.i.i, 0
  %shl.i111.23.i342.i.i = select i1 %cmp3.i.23.i341.i.i, i32 0, i32 0
  %c23.i343.i.i = shl i32 %conv85.23.i340.i.i, %shl.i111.23.i342.i.i
  %and.23.i344.i.i = and i32 %and.22.i337.i.i, %c23.i343.i.i
  %2 = trunc i64 0 to i32
  %conv85.24.i347.i.i = or i32 0, %2
  %cmp3.i.24.i348.i.i = icmp ugt i32 %conv85.24.i347.i.i, 0
  %shl.i111.24.i349.i.i = select i1 %cmp3.i.24.i348.i.i, i32 0, i32 0
  %c24.i350.i.i = shl i32 %conv85.24.i347.i.i, %shl.i111.24.i349.i.i
  %and.24.i351.i.i = and i32 %and.23.i344.i.i, %c24.i350.i.i
  %3 = trunc i64 0 to i32
  %conv85.25.i354.i.i = or i32 0, %3
  %cmp3.i.25.i355.i.i = icmp ugt i32 %conv85.25.i354.i.i, 0
  %shl.i111.25.i356.i.i = select i1 %cmp3.i.25.i355.i.i, i32 0, i32 0
  %c25.i357.i.i = shl i32 %conv85.25.i354.i.i, %shl.i111.25.i356.i.i
  %and.25.i358.i.i = and i32 %and.24.i351.i.i, %c25.i357.i.i
  %conv109.i.i = trunc i32 %and.25.i358.i.i to i8
  %cmp.i.i54.i = icmp eq i8 %conv109.i.i, 0
  ret i1 %cmp.i.i54.i
}