Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: tryToFindDuplicates
Issue title: [SLP] Crash in BoUpSLP::collectValuesToDemote
Labels: llvm:SLPVectorizer
crash-on-valid
Reported by: sjoerdmeijer

This IR:

```
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64-unknown-linux-gnu"

define ptr @_Z1bbPA2_sPA2_A2_c(ptr %d) {
entry:
  %0 = load i8, ptr null, align 1
  %cmp4.2 = icmp eq i8 %0, 0
  %1 = select i1 %cmp4.2, i64 0, i64 0
  %2 = shl i64 %1, 1
  %3 = getelementptr i8, ptr %d, i64 %2
  %4 = xor i64 0, 0
  %5 = udiv i64 %4, 0
  %6 = mul i64 %5, 6
  %7 = getelementptr i8, ptr %d, i64 %6
  %8 = shl i64 %1, 0
  %scevgep42 = getelementptr i8, ptr %d, i64 %8
  %9 = mul i64 %5, 1
  %10 = getelementptr i8, ptr %d, i64 %9
  %11 = udiv i64 1, 0
  %12 = mul i64 %11, 1
  %13 = getelementptr i8, ptr %d, i64 %12
  %14 = mul i64 %11, 0
  %15 = getelementptr i8, ptr %d, i64 %14
  ret ptr %15

; uselistorder directives
  uselistorder ptr %d, { 5, 4, 3, 2, 1, 0 }
}
```

Triggers this assert:

```
opt: /root/llvm-project/llvm/include/llvm/Support/Casting.h:572: decltype(auto) llvm::cast(From*) [with To = llvm::Instruction; From = llvm::Value]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
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 "_Z1bbPA2_sPA2_A2_c"
 #0 0x0000000005944c48 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5944c48)
 #1 0x0000000005941af4 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x000076c276e42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000076c276e969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000076c276e42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000076c276e287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000076c276e2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000076c276e39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000000bc65ea (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xbc65ea)
 #9 0x00000000036b185d llvm::slpvectorizer::BoUpSLP::collectValuesToDemote(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, unsigned int&, llvm::SmallVectorImpl<unsigned int>&, llvm::DenseSet<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::DenseMapInfo<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, void>>&, llvm::SmallDenseSet<unsigned int, 8u, llvm::DenseMapInfo<unsigned int, void>> const&, unsigned int&, bool&, bool) const::'lambda10'(unsigned int, unsigned int)::operator()(unsigned int, unsigned int) const::'lambda'(llvm::Value*)::operator()(llvm::Value*) const SLPVectorizer.cpp:0:0
#10 0x00000000036b1aec bool llvm::function_ref<bool (unsigned int, unsigned int)>::callback_fn<llvm::slpvectorizer::BoUpSLP::collectValuesToDemote(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, unsigned int&, llvm::SmallVectorImpl<unsigned int>&, llvm::DenseSet<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::DenseMapInfo<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, void>>&, llvm::SmallDenseSet<unsigned int, 8u, llvm::DenseMapInfo<unsigned int, void>> const&, unsigned int&, bool&, bool) const::'lambda10'(unsigned int, unsigned int)>(long, unsigned int, unsigned int) SLPVectorizer.cpp:0:0
#11 0x00000000037363bd llvm::slpvectorizer::BoUpSLP::collectValuesToDemote(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, unsigned int&, llvm::SmallVectorImpl<unsigned int>&, llvm::DenseSet<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::DenseMapInfo<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, void>>&, llvm::SmallDenseSet<unsigned int, 8u, llvm::DenseMapInfo<unsigned int, void>> const&, unsigned int&, bool&, bool) const::'lambda6'(unsigned int&, llvm::ArrayRef<llvm::slpvectorizer::BoUpSLP::TreeEntry const*>, llvm::function_ref<bool (unsigned int, unsigned int)>)::operator()(unsigned int&, llvm::ArrayRef<llvm::slpvectorizer::BoUpSLP::TreeEntry const*>, llvm::function_ref<bool (unsigned int, unsigned int)>) const SLPVectorizer.cpp:0:0
#12 0x0000000003734455 llvm::slpvectorizer::BoUpSLP::collectValuesToDemote(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, unsigned int&, llvm::SmallVectorImpl<unsigned int>&, llvm::DenseSet<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::DenseMapInfo<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, void>>&, llvm::SmallDenseSet<unsigned int, 8u, llvm::DenseMapInfo<unsigned int, void>> const&, unsigned int&, bool&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3734455)
#13 0x00000000037365c6 llvm::slpvectorizer::BoUpSLP::collectValuesToDemote(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, unsigned int&, llvm::SmallVectorImpl<unsigned int>&, llvm::DenseSet<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::DenseMapInfo<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, void>>&, llvm::SmallDenseSet<unsigned int, 8u, llvm::DenseMapInfo<unsigned int, void>> const&, unsigned int&, bool&, bool) const::'lambda6'(unsigned int&, llvm::ArrayRef<llvm::slpvectorizer::BoUpSLP::TreeEntry const*>, llvm::function_ref<bool (unsigned int, unsigned int)>)::operator()(unsigned int&, llvm::ArrayRef<llvm::slpvectorizer::BoUpSLP::TreeEntry const*>, llvm::function_ref<bool (unsigned int, unsigned int)>) const SLPVectorizer.cpp:0:0
#14 0x00000000037340e5 llvm::slpvectorizer::BoUpSLP::collectValuesToDemote(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, unsigned int&, llvm::SmallVectorImpl<unsigned int>&, llvm::DenseSet<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::DenseMapInfo<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, void>>&, llvm::SmallDenseSet<unsigned int, 8u, llvm::DenseMapInfo<unsigned int, void>> const&, unsigned int&, bool&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x37340e5)
#15 0x0000000003736f0c llvm::slpvectorizer::BoUpSLP::computeMinimumValueSizes()::'lambda'(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, bool, unsigned int, bool, bool)::operator()(llvm::slpvectorizer::BoUpSLP::TreeEntry const&, bool, bool, unsigned int, bool, bool) const SLPVectorizer.cpp:0:0
#16 0x00000000037892b2 llvm::slpvectorizer::BoUpSLP::computeMinimumValueSizes() (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x37892b2)
#17 0x00000000037b2cec llvm::SLPVectorizerPass::tryToVectorizeList(llvm::ArrayRef<llvm::Value*>, llvm::slpvectorizer::BoUpSLP&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x37b2cec)
#18 0x00000000037b515a llvm::SLPVectorizerPass::vectorizeGEPIndices(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x37b515a)
```

See also: https://godbolt.org/z/r8Mhn8oKf

Can be triggered from source code:

```
short a;
void b(bool c, short d[][2], char h[][2][2]) {
  for (short e;;)
    for (int f = 2; f < 10; f += 3)
#pragma clang loop interleave(enable)
      for (int g((h[2][1][f] == 0) + 3); g < c + 8; g += 3)
        a = d[g][e] - d[e][g - 2];
}
```



Fix patch:
commit 154138c25f358ed812eafc2880225c3d88221e8a
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Oct 20 04:15:47 2025 -0700

    [SLP]Do not pack div-like copyable values
    
    If a main instruction in the copyables is a div-like instruction, the
    compiler cannot pack duplicates, extending with poisons, these
    instructions, being vectorize, will result in undefined behavior.
    
    Fixes #164185

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 048a3e691fe5..3f18bd70539a 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -10546,8 +10546,11 @@ static bool tryToFindDuplicates(SmallVectorImpl<Value *> &VL,
             PoisonValue::get(UniqueValues.front()->getType()));
         // Check that extended with poisons/copyable operations are still valid
         // for vectorization (div/rem are not allowed).
-        if (!S.areInstructionsWithCopyableElements() &&
-            !getSameOpcode(PaddedUniqueValues, TLI).valid()) {
+        if ((!S.areInstructionsWithCopyableElements() &&
+             !getSameOpcode(PaddedUniqueValues, TLI).valid()) ||
+            (S.areInstructionsWithCopyableElements() && S.isMulDivLikeOp() &&
+             (S.getMainOp()->isIntDivRem() || S.getMainOp()->isFPDivRem() ||
+              isa<CallInst>(S.getMainOp())))) {
           LLVM_DEBUG(dbgs() << "SLP: Scalar used twice in bundle.\n");
           ReuseShuffleIndices.clear();
           return false;


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/AArch64/div-like-mixed-with-undefs.ll
commands: opt -passes=slp-vectorizer -S -slp-threshold=-100 -mtriple=aarch64-unknown-linux-gnu < %s
tests: test_name: <module>
test_body: 
define ptr @test(ptr %d) {
;
entry:
  %0 = load i8, ptr null, align 1
  %cmp4.2 = icmp eq i8 %0, 0
  %1 = select i1 %cmp4.2, i64 0, i64 0
  %2 = shl i64 %1, 1
  %3 = getelementptr i8, ptr %d, i64 %2
  %4 = xor i64 0, 0
  %5 = udiv i64 %4, 0
  %6 = mul i64 %5, 6
  %7 = getelementptr i8, ptr %d, i64 %6
  %8 = shl i64 %1, 0
  %scevgep42 = getelementptr i8, ptr %d, i64 %8
  %9 = mul i64 %5, 1
  %10 = getelementptr i8, ptr %d, i64 %9
  %11 = udiv i64 1, 0
  %12 = mul i64 %11, 1
  %13 = getelementptr i8, ptr %d, i64 %12
  %14 = mul i64 %11, 0
  %15 = getelementptr i8, ptr %d, i64 %14
  ret ptr %15
}