Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: addMask
Issue title: [SLPVectorizer] Assertion "SubMask with many inputs support must be larger than the mask." failed.
Labels: llvm:SLPVectorizer
crash-on-valid
Reported by: dtcxzyw

Reproducer: https://godbolt.org/z/Mzbe1G875
```
; bin/opt -passes=slp-vectorizer test.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 i64 @test() {
entry:
  %xor148.2.i = xor i32 0, 0
  %conv193.i = zext i32 %xor148.2.i to i64
  %conv193.1.i = zext i32 %xor148.2.i to i64
  %or194.1.i = or i64 %conv193.i, %conv193.1.i
  %xor148.2.i.1 = xor i32 0, 0
  %conv193.i.1 = zext i32 %xor148.2.i.1 to i64
  %or194.i.1 = or i64 %or194.1.i, %conv193.i.1
  %conv193.1.i.1 = zext i32 %xor148.2.i.1 to i64
  %or194.1.i.1 = or i64 %or194.i.1, %conv193.1.i.1
  %xor148.2.i.2 = xor i32 0, 0
  %conv193.i.2 = zext i32 %xor148.2.i.2 to i64
  %or194.i.2 = or i64 %or194.1.i.1, %conv193.i.2
  %conv193.1.i.2 = zext i32 %xor148.2.i.2 to i64
  %or194.1.i.2 = or i64 %or194.i.2, %conv193.1.i.2
  %xor148.2.i.3 = xor i32 0, 0
  %conv193.i.3 = zext i32 %xor148.2.i.3 to i64
  %or194.i.3 = or i64 %or194.1.i.2, %conv193.i.3
  %conv193.1.i.3 = zext i32 %xor148.2.i.3 to i64
  %or194.1.i.3 = or i64 %or194.i.3, %conv193.1.i.3
  %xor148.2.i.4 = xor i32 0, 0
  %conv193.i.4 = zext i32 %xor148.2.i.4 to i64
  %or194.i.4 = or i64 %or194.1.i.3, %conv193.i.4
  %conv193.1.i.4 = zext i32 %xor148.2.i.4 to i64
  %or194.1.i.4 = or i64 %or194.i.4, %conv193.1.i.4
  %xor148.2.i.5 = xor i32 0, 0
  %conv193.i.5 = zext i32 %xor148.2.i.5 to i64
  %or194.i.5 = or i64 %or194.1.i.4, %conv193.i.5
  %conv193.1.i.5 = zext i32 %xor148.2.i.5 to i64
  %or194.1.i.5 = or i64 %or194.i.5, %conv193.1.i.5
  %xor148.2.i.6 = xor i32 0, 0
  %conv193.i.6 = zext i32 %xor148.2.i.6 to i64
  %or194.i.6 = or i64 %or194.1.i.5, %conv193.i.6
  %or54.i.i.6 = or i32 %xor148.2.i.6, 0
  %conv193.1.i.6 = zext i32 %or54.i.i.6 to i64
  %xor148.2.i.7 = xor i32 0, 0
  %conv193.i.7 = zext i32 %xor148.2.i.7 to i64
  %0 = or i64 %or194.i.6, %conv193.i.7
  %conv193.1.i.7 = zext i32 %xor148.2.i.7 to i64
  %1 = or i64 %0, %conv193.1.i.7
  %or194.1.i.7 = or i64 %1, %conv193.1.i.6
  ret i64 %or194.1.i.7
}
```
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:1143: void addMask(llvm::SmallVectorImpl<int>&, llvm::ArrayRef<int>, bool): Assertion `(!ExtendingManyInputs || SubMask.size() > Mask.size() || (SubMask.size() == Mask.size() && std::all_of(std::next(Mask.begin(), Mask.size() / 2), Mask.end(), [](int Idx) { return Idx == PoisonMaskElem; }))) && "SubMask with many inputs support must be larger than the mask."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "test"
 #0 0x00000000051b7378 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x51b7378)
 #1 0x00000000051b4d6c SignalHandler(int) Signals.cpp:0:0
 #2 0x0000751221842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007512218969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x0000751221842476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007512218287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000075122182871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x0000751221839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x00000000041e91f7 llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator::finalize(llvm::ArrayRef<int>, llvm::ArrayRef<std::pair<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, unsigned int>>, llvm::ArrayRef<int>, unsigned int, llvm::function_ref<void (llvm::Value*&, llvm::SmallVectorImpl<int>&)>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41e91f7)
 #9 0x00000000042256f9 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*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x42256f9)
#10 0x000000000422f707 llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x422f707)
#11 0x00000000042636a1 llvm::slpvectorizer::BoUpSLP::getTreeCost(llvm::ArrayRef<llvm::Value*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x42636a1)
#12 0x00000000042691b0 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#13 0x000000000426c681 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x426c681)
#14 0x0000000004270deb llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#15 0x00000000042758a6 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x42758a6)
#16 0x000000000427bf86 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 0x000000000427ca9b llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x427ca9b)
#18 0x0000000002fcc5ce 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+0x2fcc5ce)
#19 0x0000000004fb6a68 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fb6a68)
#20 0x0000000000e3dd4e 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+0xe3dd4e)
#21 0x0000000004fb548e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fb548e)
#22 0x0000000000e3d3fe 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+0xe3d3fe)
#23 0x0000000004fb4ec0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fb4ec0)
#24 0x000000000090ce7a 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) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x90ce7a)
#25 0x00000000008ff519 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ff519)
#26 0x0000751221829d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#27 0x0000751221829e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#28 0x00000000008f6d6e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f6d6e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


Fix patch:
commit 57bbdbd7ae3698a274edd4dd6ef1b53d9129e552
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Nov 25 07:56:45 2024 -0800

    [SLP]Relax assertion in mask combine for non-power-of-2 number of elements
    
    The nodes may contain non-power-of-2 number of elements. Need to relax
    the assertion to avoid possible compiler crash
    
    Fixes #117517

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index d033b7c2ef4a..73218f377a06 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -1143,9 +1143,7 @@ static void addMask(SmallVectorImpl<int> &Mask, ArrayRef<int> SubMask,
   assert(
       (!ExtendingManyInputs || SubMask.size() > Mask.size() ||
        // Check if input scalars were extended to match the size of other node.
-       (SubMask.size() == Mask.size() &&
-        std::all_of(std::next(Mask.begin(), Mask.size() / 2), Mask.end(),
-                    [](int Idx) { return Idx == PoisonMaskElem; }))) &&
+       (SubMask.size() == Mask.size() && Mask.back() == PoisonMaskElem)) &&
       "SubMask with many inputs support must be larger than the mask.");
   if (Mask.empty()) {
     Mask.append(SubMask.begin(), SubMask.end());


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/non-power-2-num-elems-reused.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-10 < %s
tests: test_name: <module>
test_body: 
define i64 @test() {
;
entry:
  %xor148.2.i = xor i32 0, 0
  %conv193.i = zext i32 %xor148.2.i to i64
  %conv193.1.i = zext i32 %xor148.2.i to i64
  %or194.1.i = or i64 %conv193.i, %conv193.1.i
  %xor148.2.i.1 = xor i32 0, 0
  %conv193.i.1 = zext i32 %xor148.2.i.1 to i64
  %or194.i.1 = or i64 %or194.1.i, %conv193.i.1
  %conv193.1.i.1 = zext i32 %xor148.2.i.1 to i64
  %or194.1.i.1 = or i64 %or194.i.1, %conv193.1.i.1
  %xor148.2.i.2 = xor i32 0, 0
  %conv193.i.2 = zext i32 %xor148.2.i.2 to i64
  %or194.i.2 = or i64 %or194.1.i.1, %conv193.i.2
  %conv193.1.i.2 = zext i32 %xor148.2.i.2 to i64
  %or194.1.i.2 = or i64 %or194.i.2, %conv193.1.i.2
  %xor148.2.i.3 = xor i32 0, 0
  %conv193.i.3 = zext i32 %xor148.2.i.3 to i64
  %or194.i.3 = or i64 %or194.1.i.2, %conv193.i.3
  %conv193.1.i.3 = zext i32 %xor148.2.i.3 to i64
  %or194.1.i.3 = or i64 %or194.i.3, %conv193.1.i.3
  %xor148.2.i.4 = xor i32 0, 0
  %conv193.i.4 = zext i32 %xor148.2.i.4 to i64
  %or194.i.4 = or i64 %or194.1.i.3, %conv193.i.4
  %conv193.1.i.4 = zext i32 %xor148.2.i.4 to i64
  %or194.1.i.4 = or i64 %or194.i.4, %conv193.1.i.4
  %xor148.2.i.5 = xor i32 0, 0
  %conv193.i.5 = zext i32 %xor148.2.i.5 to i64
  %or194.i.5 = or i64 %or194.1.i.4, %conv193.i.5
  %conv193.1.i.5 = zext i32 %xor148.2.i.5 to i64
  %or194.1.i.5 = or i64 %or194.i.5, %conv193.1.i.5
  %xor148.2.i.6 = xor i32 0, 0
  %conv193.i.6 = zext i32 %xor148.2.i.6 to i64
  %or194.i.6 = or i64 %or194.1.i.5, %conv193.i.6
  %or54.i.i.6 = or i32 %xor148.2.i.6, 0
  %conv193.1.i.6 = zext i32 %or54.i.i.6 to i64
  %xor148.2.i.7 = xor i32 0, 0
  %conv193.i.7 = zext i32 %xor148.2.i.7 to i64
  %0 = or i64 %or194.i.6, %conv193.i.7
  %conv193.1.i.7 = zext i32 %xor148.2.i.7 to i64
  %1 = or i64 %0, %conv193.1.i.7
  %or194.1.i.7 = or i64 %1, %conv193.1.i.6
  ret i64 %or194.1.i.7
}