commit f953b5eb72df77fc301aac210eab31c6270ff771
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Nov 25 08:29:22 2024 -0800

    [SLP]Relax assertion about subvectors mask size

    SubVectorsMask might be less than CommonMask, if the vectors with larger
    number of elements are permuted or reused elements are used. Need to
    consider this when estimation/building the vector to avoid compiler
    crash

    Fixes #117518

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 73218f377a06..34b80c1e3608 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -10875,9 +10875,10 @@ public:
           CommonMask[Idx] = Idx;
       // Add subvectors permutation cost.
       if (!SubVectorsMask.empty()) {
-        assert(SubVectorsMask.size() == CommonMask.size() &&
+        assert(SubVectorsMask.size() <= CommonMask.size() &&
                "Expected same size of masks for subvectors and common mask.");
-        SmallVector<int> SVMask(SubVectorsMask.begin(), SubVectorsMask.end());
+        SmallVector<int> SVMask(CommonMask.size(), PoisonMaskElem);
+        copy(SubVectorsMask, SVMask.begin());
         for (auto [I1, I2] : zip(SVMask, CommonMask)) {
           if (I2 != PoisonMaskElem) {
             assert(I1 == PoisonMaskElem && "Expected unused subvectors mask");
@@ -14372,7 +14373,8 @@ public:
       if (SubVectorsMask.empty()) {
         Vec = CreateSubVectors(Vec, CommonMask);
       } else {
-        SmallVector<int> SVMask(SubVectorsMask.begin(), SubVectorsMask.end());
+        SmallVector<int> SVMask(CommonMask.size(), PoisonMaskElem);
+        copy(SubVectorsMask, SVMask.begin());
         for (auto [I1, I2] : zip(SVMask, CommonMask)) {
           if (I2 != PoisonMaskElem) {
             assert(I1 == PoisonMaskElem && "Expected unused subvectors mask");

opt -S --passes=slp-vectorizer -slp-threshold=-300 -mtriple=x86_64-unknown-linux-gnu < %s

define void @test() {
;
  %xor108.i.i.i = xor i64 0, 1
  %conv115.i.i.i = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i = or i16 %conv115.i.i.i, 0
  %add.i.frozen.i.i.i = freeze i16 %add.i.i.i.i
  %.cmp.not.i.i.i = icmp eq i16 %add.i.frozen.i.i.i, 0
  %cond.i1002.1.i.i.i = lshr i64 0, 0
  %conv115.1.i.i.i = trunc i64 %cond.i1002.1.i.i.i to i16
  %add.i.1.i.i.i = or i16 %conv115.1.i.i.i, 0
  %add.i.frozen.1.i.i.i = freeze i16 %add.i.1.i.i.i
  %.cmp.not.1.i.i.i = icmp eq i16 %add.i.frozen.1.i.i.i, 0
  %cond.i1002.2.i.i.i = lshr i64 %xor108.i.i.i, 0
  %conv115.2.i.i.i = trunc i64 %cond.i1002.2.i.i.i to i16
  %add.i.2.i.i.i = or i16 %conv115.2.i.i.i, 0
  %add.i.frozen.2.i.i.i = freeze i16 %add.i.2.i.i.i
  %.cmp.not.2.i.i.i = icmp eq i16 %add.i.frozen.2.i.i.i, 0
  %cond.i1002.3.i.i.i = lshr i64 0, 0
  %conv115.3.i.i.i = trunc i64 %cond.i1002.3.i.i.i to i16
  %add.i.3.i.i.i = or i16 %conv115.3.i.i.i, 0
  %add.i.frozen.3.i.i.i = freeze i16 %add.i.3.i.i.i
  %.cmp.not.3.i.i.i = icmp eq i16 %add.i.frozen.3.i.i.i, 0
  %conv115.i.i.i.1 = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i.1 = or i16 %conv115.i.i.i.1, 0
  %add.i.frozen.i.i.i.1 = freeze i16 %add.i.i.i.i.1
  %.cmp.not.i.i.i.1 = icmp eq i16 %add.i.frozen.i.i.i.1, 0
  %cond.i1002.1.i.i.i.1 = lshr i64 0, 0
  %conv115.1.i.i.i.1 = trunc i64 %cond.i1002.1.i.i.i.1 to i16
  %add.i.1.i.i.i.1 = or i16 %conv115.1.i.i.i.1, 0
  %add.i.frozen.1.i.i.i.1 = freeze i16 %add.i.1.i.i.i.1
  %.cmp.not.1.i.i.i.1 = icmp eq i16 %add.i.frozen.1.i.i.i.1, 0
  %cond.i1002.2.i.i.i.1 = lshr i64 0, 0
  %conv115.2.i.i.i.1 = trunc i64 %cond.i1002.2.i.i.i.1 to i16
  %add.i.2.i.i.i.1 = or i16 %conv115.2.i.i.i.1, 0
  %add.i.frozen.2.i.i.i.1 = freeze i16 %add.i.2.i.i.i.1
  %.cmp.not.2.i.i.i.1 = icmp eq i16 %add.i.frozen.2.i.i.i.1, 0
  %cond.i1002.3.i.i.i.1 = lshr i64 0, 0
  %conv115.3.i.i.i.1 = trunc i64 %cond.i1002.3.i.i.i.1 to i16
  %add.i.3.i.i.i.1 = or i16 %conv115.3.i.i.i.1, 0
  %add.i.frozen.3.i.i.i.1 = freeze i16 %add.i.3.i.i.i.1
  %.cmp.not.3.i.i.i.1 = icmp eq i16 %add.i.frozen.3.i.i.i.1, 0
  %conv115.i.i.i.2 = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i.2 = or i16 %conv115.i.i.i.2, 0
  %add.i.frozen.i.i.i.2 = freeze i16 %add.i.i.i.i.2
  %.cmp.not.i.i.i.2 = icmp eq i16 %add.i.frozen.i.i.i.2, 0
  %cond.i1002.1.i.i.i.2 = lshr i64 0, 0
  %conv115.1.i.i.i.2 = trunc i64 %cond.i1002.1.i.i.i.2 to i16
  %add.i.1.i.i.i.2 = or i16 %conv115.1.i.i.i.2, 0
  %add.i.frozen.1.i.i.i.2 = freeze i16 %add.i.1.i.i.i.2
  %.cmp.not.1.i.i.i.2 = icmp eq i16 %add.i.frozen.1.i.i.i.2, 0
  %cond.i1002.2.i.i.i.2 = lshr i64 0, 0
  %conv115.2.i.i.i.2 = trunc i64 %cond.i1002.2.i.i.i.2 to i16
  %add.i.2.i.i.i.2 = or i16 %conv115.2.i.i.i.2, 0
  %add.i.frozen.2.i.i.i.2 = freeze i16 %add.i.2.i.i.i.2
  %.cmp.not.2.i.i.i.2 = icmp eq i16 %add.i.frozen.2.i.i.i.2, 0
  %cond.i1002.3.i.i.i.2 = lshr i64 0, 0
  %conv115.3.i.i.i.2 = trunc i64 %cond.i1002.3.i.i.i.2 to i16
  %add.i.3.i.i.i.2 = or i16 %conv115.3.i.i.i.2, 0
  %add.i.frozen.3.i.i.i.2 = freeze i16 %add.i.3.i.i.i.2
  %.cmp.not.3.i.i.i.2 = icmp eq i16 %add.i.frozen.3.i.i.i.2, 0
  %conv115.i.i.i.3 = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i.3 = or i16 %conv115.i.i.i.3, 0
  %add.i.frozen.i.i.i.3 = freeze i16 %add.i.i.i.i.3
  %.cmp.not.i.i.i.3 = icmp eq i16 %add.i.frozen.i.i.i.3, 0
  %cond.i1002.1.i.i.i.3 = lshr i64 0, 0
  %conv115.1.i.i.i.3 = trunc i64 %cond.i1002.1.i.i.i.3 to i16
  %add.i.1.i.i.i.3 = or i16 %conv115.1.i.i.i.3, 0
  %add.i.frozen.1.i.i.i.3 = freeze i16 %add.i.1.i.i.i.3
  %.cmp.not.1.i.i.i.3 = icmp eq i16 %add.i.frozen.1.i.i.i.3, 0
  %cond.i1002.2.i.i.i.3 = lshr i64 0, 0
  %conv115.2.i.i.i.3 = trunc i64 %cond.i1002.2.i.i.i.3 to i16
  %add.i.2.i.i.i.3 = or i16 %conv115.2.i.i.i.3, 0
  %add.i.frozen.2.i.i.i.3 = freeze i16 %add.i.2.i.i.i.3
  %.cmp.not.2.i.i.i.3 = icmp eq i16 %add.i.frozen.2.i.i.i.3, 0
  %cond.i1002.3.i.i.i.3 = lshr i64 0, 0
  %conv115.3.i.i.i.3 = trunc i64 %cond.i1002.3.i.i.i.3 to i16
  %add.i.3.i.i.i.3 = or i16 %conv115.3.i.i.i.3, 0
  %add.i.frozen.3.i.i.i.3 = freeze i16 %add.i.3.i.i.i.3
  %.cmp.not.3.i.i.i.3 = icmp eq i16 %add.i.frozen.3.i.i.i.3, 0
  ret void
}

[SLPVectorizer] Assertion `SubVectorsMask.size() == CommonMask.size() && "Expected same size of masks for subvectors and common mask."' failed.

Reproducer: https://godbolt.org/z/chKcKacPK
```
; 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 void @test() {
  %xor108.i.i.i = xor i64 0, 1
  %conv115.i.i.i = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i = or i16 %conv115.i.i.i, 0
  %add.i.frozen.i.i.i = freeze i16 %add.i.i.i.i
  %.cmp.not.i.i.i = icmp eq i16 %add.i.frozen.i.i.i, 0
  %cond.i1002.1.i.i.i = lshr i64 0, 0
  %conv115.1.i.i.i = trunc i64 %cond.i1002.1.i.i.i to i16
  %add.i.1.i.i.i = or i16 %conv115.1.i.i.i, 0
  %add.i.frozen.1.i.i.i = freeze i16 %add.i.1.i.i.i
  %.cmp.not.1.i.i.i = icmp eq i16 %add.i.frozen.1.i.i.i, 0
  %cond.i1002.2.i.i.i = lshr i64 %xor108.i.i.i, 0
  %conv115.2.i.i.i = trunc i64 %cond.i1002.2.i.i.i to i16
  %add.i.2.i.i.i = or i16 %conv115.2.i.i.i, 0
  %add.i.frozen.2.i.i.i = freeze i16 %add.i.2.i.i.i
  %.cmp.not.2.i.i.i = icmp eq i16 %add.i.frozen.2.i.i.i, 0
  %cond.i1002.3.i.i.i = lshr i64 0, 0
  %conv115.3.i.i.i = trunc i64 %cond.i1002.3.i.i.i to i16
  %add.i.3.i.i.i = or i16 %conv115.3.i.i.i, 0
  %add.i.frozen.3.i.i.i = freeze i16 %add.i.3.i.i.i
  %.cmp.not.3.i.i.i = icmp eq i16 %add.i.frozen.3.i.i.i, 0
  %conv115.i.i.i.1 = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i.1 = or i16 %conv115.i.i.i.1, 0
  %add.i.frozen.i.i.i.1 = freeze i16 %add.i.i.i.i.1
  %.cmp.not.i.i.i.1 = icmp eq i16 %add.i.frozen.i.i.i.1, 0
  %cond.i1002.1.i.i.i.1 = lshr i64 0, 0
  %conv115.1.i.i.i.1 = trunc i64 %cond.i1002.1.i.i.i.1 to i16
  %add.i.1.i.i.i.1 = or i16 %conv115.1.i.i.i.1, 0
  %add.i.frozen.1.i.i.i.1 = freeze i16 %add.i.1.i.i.i.1
  %.cmp.not.1.i.i.i.1 = icmp eq i16 %add.i.frozen.1.i.i.i.1, 0
  %cond.i1002.2.i.i.i.1 = lshr i64 0, 0
  %conv115.2.i.i.i.1 = trunc i64 %cond.i1002.2.i.i.i.1 to i16
  %add.i.2.i.i.i.1 = or i16 %conv115.2.i.i.i.1, 0
  %add.i.frozen.2.i.i.i.1 = freeze i16 %add.i.2.i.i.i.1
  %.cmp.not.2.i.i.i.1 = icmp eq i16 %add.i.frozen.2.i.i.i.1, 0
  %cond.i1002.3.i.i.i.1 = lshr i64 0, 0
  %conv115.3.i.i.i.1 = trunc i64 %cond.i1002.3.i.i.i.1 to i16
  %add.i.3.i.i.i.1 = or i16 %conv115.3.i.i.i.1, 0
  %add.i.frozen.3.i.i.i.1 = freeze i16 %add.i.3.i.i.i.1
  %.cmp.not.3.i.i.i.1 = icmp eq i16 %add.i.frozen.3.i.i.i.1, 0
  %conv115.i.i.i.2 = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i.2 = or i16 %conv115.i.i.i.2, 0
  %add.i.frozen.i.i.i.2 = freeze i16 %add.i.i.i.i.2
  %.cmp.not.i.i.i.2 = icmp eq i16 %add.i.frozen.i.i.i.2, 0
  %cond.i1002.1.i.i.i.2 = lshr i64 0, 0
  %conv115.1.i.i.i.2 = trunc i64 %cond.i1002.1.i.i.i.2 to i16
  %add.i.1.i.i.i.2 = or i16 %conv115.1.i.i.i.2, 0
  %add.i.frozen.1.i.i.i.2 = freeze i16 %add.i.1.i.i.i.2
  %.cmp.not.1.i.i.i.2 = icmp eq i16 %add.i.frozen.1.i.i.i.2, 0
  %cond.i1002.2.i.i.i.2 = lshr i64 0, 0
  %conv115.2.i.i.i.2 = trunc i64 %cond.i1002.2.i.i.i.2 to i16
  %add.i.2.i.i.i.2 = or i16 %conv115.2.i.i.i.2, 0
  %add.i.frozen.2.i.i.i.2 = freeze i16 %add.i.2.i.i.i.2
  %.cmp.not.2.i.i.i.2 = icmp eq i16 %add.i.frozen.2.i.i.i.2, 0
  %cond.i1002.3.i.i.i.2 = lshr i64 0, 0
  %conv115.3.i.i.i.2 = trunc i64 %cond.i1002.3.i.i.i.2 to i16
  %add.i.3.i.i.i.2 = or i16 %conv115.3.i.i.i.2, 0
  %add.i.frozen.3.i.i.i.2 = freeze i16 %add.i.3.i.i.i.2
  %.cmp.not.3.i.i.i.2 = icmp eq i16 %add.i.frozen.3.i.i.i.2, 0
  %conv115.i.i.i.3 = trunc i64 %xor108.i.i.i to i16
  %add.i.i.i.i.3 = or i16 %conv115.i.i.i.3, 0
  %add.i.frozen.i.i.i.3 = freeze i16 %add.i.i.i.i.3
  %.cmp.not.i.i.i.3 = icmp eq i16 %add.i.frozen.i.i.i.3, 0
  %cond.i1002.1.i.i.i.3 = lshr i64 0, 0
  %conv115.1.i.i.i.3 = trunc i64 %cond.i1002.1.i.i.i.3 to i16
  %add.i.1.i.i.i.3 = or i16 %conv115.1.i.i.i.3, 0
  %add.i.frozen.1.i.i.i.3 = freeze i16 %add.i.1.i.i.i.3
  %.cmp.not.1.i.i.i.3 = icmp eq i16 %add.i.frozen.1.i.i.i.3, 0
  %cond.i1002.2.i.i.i.3 = lshr i64 0, 0
  %conv115.2.i.i.i.3 = trunc i64 %cond.i1002.2.i.i.i.3 to i16
  %add.i.2.i.i.i.3 = or i16 %conv115.2.i.i.i.3, 0
  %add.i.frozen.2.i.i.i.3 = freeze i16 %add.i.2.i.i.i.3
  %.cmp.not.2.i.i.i.3 = icmp eq i16 %add.i.frozen.2.i.i.i.3, 0
  %cond.i1002.3.i.i.i.3 = lshr i64 0, 0
  %conv115.3.i.i.i.3 = trunc i64 %cond.i1002.3.i.i.i.3 to i16
  %add.i.3.i.i.i.3 = or i16 %conv115.3.i.i.i.3, 0
  %add.i.frozen.3.i.i.i.3 = freeze i16 %add.i.3.i.i.i.3
  %.cmp.not.3.i.i.i.3 = icmp eq i16 %add.i.frozen.3.i.i.i.3, 0
  ret void
}
```
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:10880: llvm::InstructionCost llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator::finalize(llvm::ArrayRef<int>, llvm::ArrayRef<std::pair<const llvm::slpvectorizer::BoUpSLP::TreeEntry*, unsigned int> >, llvm::ArrayRef<int>, unsigned int, llvm::function_ref<void(llvm::Value*&, llvm::SmallVectorImpl<int>&)>): Assertion `SubVectorsMask.size() == CommonMask.size() && "Expected same size of masks for subvectors and common 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 0x00007ac42d642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007ac42d6969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007ac42d642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007ac42d6287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00007ac42d62871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x00007ac42d639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x00000000041e9132 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+0x41e9132)
 #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 0x000000000426d57c llvm::SLPVectorizerPass::tryToVectorizeList(llvm::ArrayRef<llvm::Value*>, llvm::slpvectorizer::BoUpSLP&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x426d57c)
#13 0x000000000427168f bool llvm::SLPVectorizerPass::vectorizeCmpInsts<std::reverse_iterator<llvm::CmpInst* const*>>(llvm::iterator_range<std::reverse_iterator<llvm::CmpInst* const*>>, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x427168f)
#14 0x0000000004271fdb llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&)::'lambda3'(bool)::operator()(bool) const SLPVectorizer.cpp:0:0
#15 0x0000000004275785 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4275785)
#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 0x00007ac42d629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#27 0x00007ac42d629e40 __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
```


commit de29b850f03092195bf21f3a39402adb4ed3c216
Author: Nikita Popov <npopov@redhat.com>
Date:   Tue Jul 16 11:40:04 2024 +0200

    [InstSimplify] Fix simplifyAndOrWithICmpEq with undef refinement (#98898)

    The final case in Simplify (where Res == Absorber and the predicate is
    inverted) is not generally safe when the simplification is a refinement.
    In particular, we may simplify assuming a specific value for undef, but
    then chose a different one later.

    However, it *is* safe to refine poison in this context, unlike in the
    equivalent select folds. This is the reason why this fold did not use
    AllowRefinement=false in the first place, and using that option would
    introduce a lot of test regressions.

    This patch takes the middle path of disabling undef refinements in
    particular using the getWithoutUndef() SimplifyQuery option. However,
    this option doesn't actually work in this case, because the problematic
    fold is inside constant folding, and we currently don't propagate this
    option all the way from InstSimplify over ConstantFolding to
    ConstantFold. Work around this by explicitly checking for undef operands
    in simplifyWithOpReplaced().

    Finally, make sure that places where AllowRefinement=false also use
    Q.getWithoutUndef(). I don't have a specific test case for this (the
    original one does not work because we don't simplify selects with
    constant condition in this mode in the first place) but this seems like
    the correct thing to do to be conservative.

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

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 242c200f7ef1..3a7ae577bb06 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1975,13 +1975,16 @@ static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
     return nullptr;
   };

-  if (Value *Res =
-          simplifyWithOpReplaced(Op1, A, B, Q, /* AllowRefinement */ true,
-                                 /* DropFlags */ nullptr, MaxRecurse))
+  // In the final case (Res == Absorber with inverted predicate), it is safe to
+  // refine poison during simplification, but not undef. For simplicity always
+  // disable undef-based folds here.
+  if (Value *Res = simplifyWithOpReplaced(Op1, A, B, Q.getWithoutUndef(),
+                                          /* AllowRefinement */ true,
+                                          /* DropFlags */ nullptr, MaxRecurse))
     return Simplify(Res);
-  if (Value *Res =
-          simplifyWithOpReplaced(Op1, B, A, Q, /* AllowRefinement */ true,
-                                 /* DropFlags */ nullptr, MaxRecurse))
+  if (Value *Res = simplifyWithOpReplaced(Op1, B, A, Q.getWithoutUndef(),
+                                          /* AllowRefinement */ true,
+                                          /* DropFlags */ nullptr, MaxRecurse))
     return Simplify(Res);

   return nullptr;
@@ -4300,6 +4303,9 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                      bool AllowRefinement,
                                      SmallVectorImpl<Instruction *> *DropFlags,
                                      unsigned MaxRecurse) {
+  assert((AllowRefinement || !Q.CanUseUndef) &&
+         "If AllowRefinement=false then CanUseUndef=false");
+
   // Trivial replacement.
   if (V == Op)
     return RepOp;
@@ -4347,6 +4353,11 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
     } else {
       NewOps.push_back(InstOp);
     }
+
+    // Bail out if any operand is undef and SimplifyQuery disables undef
+    // simplification. Constant folding currently doesn't respect this option.
+    if (isa<UndefValue>(NewOps.back()) && !Q.CanUseUndef)
+      return nullptr;
   }

   if (!AnyReplaced)
@@ -4467,6 +4478,11 @@ Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                     const SimplifyQuery &Q,
                                     bool AllowRefinement,
                                     SmallVectorImpl<Instruction *> *DropFlags) {
+  // If refinement is disabled, also disable undef simplifications (which are
+  // always refinements) in SimplifyQuery.
+  if (!AllowRefinement)
+    return ::simplifyWithOpReplaced(V, Op, RepOp, Q.getWithoutUndef(),
+                                    AllowRefinement, DropFlags, RecursionLimit);
   return ::simplifyWithOpReplaced(V, Op, RepOp, Q, AllowRefinement, DropFlags,
                                   RecursionLimit);
 }
@@ -4606,7 +4622,7 @@ static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
                                        Value *TrueVal, Value *FalseVal,
                                        const SimplifyQuery &Q,
                                        unsigned MaxRecurse) {
-  if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q,
+  if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q.getWithoutUndef(),
                              /* AllowRefinement */ false,
                              /* DropFlags */ nullptr, MaxRecurse) == TrueVal)
     return FalseVal;

define i1 @and_is_constant(ptr %arg, ptr %arg2) {
  %icmp = icmp eq ptr %arg, %arg2
  %call = call i1 @llvm.is.constant.i1(i1 %icmp)
  %and = and i1 %call, %icmp
  ret i1 %and
}

; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
declare i1 @llvm.is.constant.i1(i1) #0

attributes #0 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }

define i1 @pr98753(i32 noundef %x, i32 %y) {
  %cmp1 = icmp ne i32 %x, 0
  %sel = select i1 %cmp1, i32 %y, i32 undef
  %cmp2 = icmp sgt i32 %sel, 0
  %and = and i1 %cmp1, %cmp2
  ret i1 %and
}

Miscompilation with libstdc++'s std::optional<int> and -O1

https://godbolt.org/z/KjEreWf57

With Clang 18.1 and libstdc++, we get different behavior when compared to Clang 17 in the code below.
EDIT: requires at least -O1.

```cpp
#include <optional>
#include <iostream>

// defined in a separate compilation unit
int takeIntRefAndReturn0(int&);

std::optional<int> shouldReturnEmptyOptional() {
  int v = 5;
  if (takeIntRefAndReturn0(v))
    return v;
  return std::nullopt;
}

int main() {
  auto opt = shouldReturnEmptyOptional();
  if (opt && *opt > 0) {
    std::cout << "SHOULD NOT BE PRINTED: *opt = " << *opt << std::endl;
    return 1;
  }
  std::cout << "SHOULD BE PRINTED" << std::endl;
}
```

With Clang 17, we get `SHOULD BE PRINTED`, while with with Clang 18.1 we get  `SHOULD NOT BE PRINTED: *opt = 5`.

With git-bisect, I found that this is caused by https://github.com/llvm/llvm-project/commit/060de415af335fdd82910f409e2be3b8457eaa43.

An isomorphic example to reproduce this (https://godbolt.org/z/9PsjY17sT):
```cpp
int takeIntRefReturn0(int &);
void assertNotReached(int);

static bool logicalAnd(bool a, bool b) { return a && b; }

int main() {
  int v4;
  bool v3;
  {
    int v1 = 5;
    int v2 = takeIntRefReturn0(v1);
    v3 = v2 != 0;
    if (v3)
      v4 = v1;
  }
  // Move  to a function so that && is not short cutted.
  // v4 will be undefined if v2 == 0, but v3 is false, so the branch shouldn't be entered.
  if (logicalAnd(v3, v4 > 0))
    assertNotReached(v4);

  return 0;
}
```
Note in the generated LLVM IR that
```llvm
%6 = icmp sgt i32 %5, 0
%7 = and i1 %3, %6
br i1 %7, label %8, label %9
```
was reduced to only
```llvm
%6 = icmp sgt i32 %5, 0
br i1 %6, label %7, label %8
```

Reproducer: https://alive2.llvm.org/ce/z/p4ZGxe
```
; bin/opt -passes=instcombine test.ll -S
define i1 @src(i32 noundef %x, i32 %y) {
  %3 = icmp ne i32 %x, 0
  %5 = select i1 %3, i32 %y, i32 undef
  %6 = icmp sgt i32 %5, 0
  %7 = and i1 %3, %6
  br i1 %7, label %if.then, label %if.else

if.then:
  call void @use(i32 noundef %5)
  ret i1 true

if.else:
  ret i1 false
}

define i1 @tgt(i32 noundef %x, i32 %y) {
  %.not = icmp eq i32 %x, 0
  %1 = select i1 %.not, i32 undef, i32 %y
  %2 = icmp sgt i32 %1, 0
  br i1 %2, label %if.then, label %if.else

if.then:                                          ; preds = %0
  call void @use(i32 noundef %1)
  ret i1 true

if.else:                                          ; preds = %0
  ret i1 false
}

declare void @use(i32 %x)
```
cc @nikic

A bit simpler using just instsimplify: https://alive2.llvm.org/ce/z/tnkf6A

I expect the fix here is to perform replacements with `Q.getWithoutUndef()`. But probably not just here, but also in other places using simplifyWithOpReplaced(). (Possibly making it always use that mode.)

Thanks a lot for fixing this so quickly! I wonder if this should be included in 18.1.9?

The LLVM 18 branch is already closed, there will be no further releases.

I'll add the milestone anyway as it's easier to track for downstream backports then.


commit beba307c5bc206168bdea3b893e02ea31579fe62
Author: Nikita Popov <npopov@redhat.com>
Date:   Tue Mar 12 16:23:25 2024 +0100

    [LSR] Clear SCEVExpander before deleting phi nodes

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

diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 8b078ddc4e74..c4e1a0db8b32 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -6971,6 +6971,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
     Rewriter.setDebugType(DEBUG_TYPE);
 #endif
     unsigned numFolded = Rewriter.replaceCongruentIVs(L, &DT, DeadInsts, &TTI);
+    Rewriter.clear();
     if (numFolded) {
       Changed = true;
       RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI,
@@ -6989,6 +6990,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
     SCEVExpander Rewriter(SE, DL, "lsr", true);
     int Rewrites = rewriteLoopExitValues(L, &LI, &TLI, &SE, &TTI, Rewriter, &DT,
                                          UnusedIndVarInLoop, DeadInsts);
+    Rewriter.clear();
     if (Rewrites) {
       Changed = true;
       RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI,

define i64 @test() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb5, %bb
  %phi = phi i8 [ %zext6, %bb5 ], [ 0, %bb ]
  br label %bb2

bb2:                                              ; preds = %bb2, %bb1
  %phi3 = phi i8 [ %add, %bb2 ], [ %phi, %bb1 ]
  %phi4 = phi i32 [ 0, %bb2 ], [ 1, %bb1 ]
  %add = add i8 %phi3, 1
  br i1 true, label %bb5, label %bb2

bb5:                                              ; preds = %bb2
  %zext = zext i8 %add to i32
  %icmp = icmp sge i32 %phi4, 0
  %zext6 = zext i1 %icmp to i8
  br label %bb1
}

[LSR] crashed on "asserting value handle still pointed to this value!"

https://godbolt.org/z/MWWcGdxT5
LSR crashed when deleting dead PHIs

I will give a resolution to fix it later.

#84777 For this case, I think we should not set the value with nullptr when the value's uses are not empty.

Reduced:
```llvm
define i64 @test() {
bb:
  br label %bb1

bb1:
  %phi = phi i8 [ %zext6, %bb5 ], [ 0, %bb ]
  br label %bb2

bb2:
  %phi3 = phi i8 [ %add, %bb2 ], [ %phi, %bb1 ]
  %phi4 = phi i32 [ 0, %bb2 ], [ 1, %bb1 ]
  %add = add i8 %phi3, 1
  br i1 true, label %bb5, label %bb2

bb5:
  %zext = zext i8 %add to i32
  %icmp = icmp sge i32 %phi4, 0
  %zext6 = zext i1 %icmp to i8
  br label %bb1
}
```


commit 70091dc943ade280d75cea1e5ea5e93d9a8f934a
Author: Antonio Frighetto <me@antoniofrighetto.com>
Date:   Sat May 18 16:52:17 2024 +0200

    [LICM] Invalidate cached SCEV results in `hoistMulAddAssociation`

    While reassociating expressions, LICM is required to invalidate SCEV
    results, as otherwise subsequent passes in the pipeline that leverage
    LICM foldings (e.g. IndVars), may reason on invalid expressions; thus
    miscompiling. This is achieved by rewriting the reassociable
    instruction from scratch.

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

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 6aa4188d1cc4..5eccf7b4adb6 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -2751,7 +2751,7 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L,
   IRBuilder<> Builder(Preheader->getTerminator());
   for (auto *U : Changes) {
     assert(L.isLoopInvariant(U->get()));
-    Instruction *Ins = cast<Instruction>(U->getUser());
+    auto *Ins = cast<BinaryOperator>(U->getUser());
     Value *Mul;
     if (I.getType()->isIntOrIntVectorTy()) {
       Mul = Builder.CreateMul(U->get(), Factor, "factor.op.mul");
@@ -2759,8 +2759,20 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L,
       Ins->dropPoisonGeneratingFlags();
     } else
       Mul = Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul");
-    U->set(Mul);
+
+    // Rewrite the reassociable instruction.
+    unsigned OpIdx = U->getOperandNo();
+    auto *LHS = OpIdx == 0 ? Mul : Ins->getOperand(0);
+    auto *RHS = OpIdx == 1 ? Mul : Ins->getOperand(1);
+    auto *NewBO = BinaryOperator::Create(Ins->getOpcode(), LHS, RHS,
+                                         Ins->getName() + ".reass", Ins);
+    NewBO->copyIRFlags(Ins);
+    if (VariantOp == Ins)
+      VariantOp = NewBO;
+    Ins->replaceAllUsesWith(NewBO);
+    eraseInstruction(*Ins, SafetyInfo, MSSAU);
   }
+
   I.replaceAllUsesWith(VariantOp);
   eraseInstruction(I, SafetyInfo, MSSAU);
   return true;

opt -S -passes='loop-unroll,loop-mssa(licm,indvars)' -unroll-count=4 < %s 2>&1

define i16 @main() {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %mul = phi i16 [ 1, %entry ], [ %mul.n, %loop ]
  %div = phi i16 [ 32767, %entry ], [ %div.n, %loop ]
  %mul.n = mul i16 %mul, 2
  %div.n = sdiv i16 %div, 2
  %cmp = icmp sgt i16 %div, 0
  br i1 %cmp, label %loop, label %end

end:                                              ; preds = %loop
  ret i16 %mul
}

Miscompile with opt -passes="loop-unroll,loop-mssa(licm,indvars)" -unroll-count=4

llvm commit: e76b257483e6c
Reproduce with:
```opt -passes="loop-unroll,loop-mssa(licm,indvars)" -unroll-count=4 bbi-95405.ll -S -o -```

The input function returns 32768, but after running the passes as above we get
```
define i16 @foo() {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  br i1 false, label %loop, label %end, !llvm.loop !0

end:                                              ; preds = %loop
  ret i16 8192
}

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.unroll.disable"}
```
So now the function returns 8192 instead.

If I extract the IR after loop-unroll or licm and run the rest of the passes instead I get the correct result.

[bbi-95405.ll.gz](https://github.com/llvm/llvm-project/files/15294896/bbi-95405.ll.gz)

This starts happening with https://github.com/llvm/llvm-project/pull/67736 , commit 2dd52046816
```
Recommit "[LICM] Support integer mul/add in hoistFPAssociation. (#67736)"

With a fix for build bot failure. I was accessing the type of a deleted
Instruction.

Original message:

The reassociation this is trying to repair can happen for integer types
too.

This patch adds support for integer mul/add to hoistFPAssociation. The
function has been renamed to hoistMulAddAssociation. I've used separate
statistics and limits for integer to allow tuning flexibility.
```

> Without looking into this in detail, it's possible that the way the LICM code modifies instructions in place results incorrect cached SCEV results.

I added some printouts and see that when IndVarSimplify run rewriteLoopExitValues we do
```
const SCEV *ExitValue = SE->getSCEVAtScope(Inst, L->getParentLoop());
```
for Inst being
```
%mul.n = mul i16 %mul, 8
```
and then we get the SCEV
```
(2 * %mul)
```
which looks wrong.

If I split up the pipeline in several opt runs we instead get the SCEV
```
(8 * %mul)
```
which looks more reasonable (and then we also get the correct result).
LICM changed
```
%mul.n = mul i16 %mul, 2
```
to
```
%mul.n = mul i16 %mul, 8
```
so yeah, it should perhaps do something (more) about SCEV.

@antoniofrighetto : nice that you work on this!

But oh it's annoying that I don't get any emails from github about that there was activity here with a linked PR with a fix etc even if I wrote this issue. :( I do get emails when there are comments but not when the issue was assigned or the PR was created. :(

> @mikaelholmen This is a bit inconvenient indeed, GH doesn’t seem to send notifications wrt that :( Closed this, thanks for reporting!

Thank you!


commit 5a90168fa34e15b544d7749ca4d247a16d360119
Author: Heejin Ahn <aheejin@gmail.com>
Date:   Wed Jan 15 11:53:51 2025 -0800

    [ValueTracking] Provide getUnderlyingObjectAggressive fallback (#123019)

    This callsite assumes `getUnderlyingObjectAggressive` returns a non-null
    pointer:

    https://github.com/llvm/llvm-project/blob/273a94b3d5a78cd9122c7b3bbb5d5a87147735d2/llvm/lib/Transforms/IPO/FunctionAttrs.cpp#L124

    But it can return null when there are cycles in the value chain so there
    is no more `Worklist` item anymore to explore, in which case it just
    returns `Object` at the end of the function without ever setting it:
    https://github.com/llvm/llvm-project/blob/9b5857a68381652dbea2a0c9efa734b6c4cf38c9/llvm/lib/Analysis/ValueTracking.cpp#L6866-L6867
    https://github.com/llvm/llvm-project/blob/9b5857a68381652dbea2a0c9efa734b6c4cf38c9/llvm/lib/Analysis/ValueTracking.cpp#L6889

    `getUnderlyingObject` does not seem to return null either judging by
    looking at its code and its callsites, so I think it is not likely to be
    the author's intention that `getUnderlyingObjectAggressive` returns
    null.

    So this checks whether `Object` is null at the end, and if so, falls
    back to the original first value.

    ---

    The test case here was reduced by bugpoint and further reduced manually,
    but I find it hard to reduce it further.

    To trigger this bug, the memory operation should not be reachable from
    the entry BB, because the `phi`s should form a cycle without introducing
    another value from the entry. I tried a minimal `phi` cycle with three
    BBs (entry BB + two BBs in a cycle), but it was skipped here:
    https://github.com/llvm/llvm-project/blob/273a94b3d5a78cd9122c7b3bbb5d5a87147735d2/llvm/lib/Transforms/IPO/FunctionAttrs.cpp#L121-L122
    To get the result that's not `ModRefInfo::NoModRef`, the length of `phi`
    chain needed to be greater than the `MaxLookup` value set in this
    function:

    https://github.com/llvm/llvm-project/blob/02403f4e450b86d93197dd34045ff40a34b21494/llvm/lib/Analysis/BasicAliasAnalysis.cpp#L744

    But just lengthening the `phi` chain to 8 didn't trigger the same error
    in `getUnderlyingObjectAggressive` because `getUnderlyingObject` here
    passes through a single-chain `phi`s so not all `phi`s end up in
    `Visited`:

    https://github.com/llvm/llvm-project/blob/9b5857a68381652dbea2a0c9efa734b6c4cf38c9/llvm/lib/Analysis/ValueTracking.cpp#L6863

    So I just submit here the smallest test case I managed to create.

    ---

    Fixes #117308 and fixes #122166.

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1bab9b32525c..1853b1c67159 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6886,7 +6886,7 @@ const Value *llvm::getUnderlyingObjectAggressive(const Value *V) {
       return FirstObject;
   } while (!Worklist.empty());

-  return Object;
+  return Object ? Object : FirstObject;
 }

 /// This is the function that does the work of looking through basic

; Regression test for a null-returning bug of getUnderlyingObjectAggressive().
; This should not crash.
define void @phi_cycle() {
bb:
  unreachable

bb1:                                              ; preds = %bb17
  br label %bb2

bb2:                                              ; preds = %bb5, %bb1
  %phi = phi ptr [ %phi6, %bb1 ], [ %phi6, %bb5 ]
  br i1 poison, label %bb4, label %bb3

bb3:                                              ; preds = %bb2
  %getelementptr = getelementptr inbounds i8, ptr %phi, i32 poison
  br label %bb5

bb4:                                              ; preds = %bb2
  br label %bb7

bb5:                                              ; preds = %bb15, %bb3
  %phi6 = phi ptr [ %getelementptr, %bb3 ], [ %phi16, %bb15 ]
  br i1 poison, label %bb17, label %bb2

bb7:                                              ; preds = %bb15, %bb4
  %phi8 = phi ptr [ %phi, %bb4 ], [ %phi16, %bb15 ]
  br i1 poison, label %bb11, label %bb9

bb9:                                              ; preds = %bb7
  %getelementptr10 = getelementptr inbounds i8, ptr %phi8, i32 1
  store i8 poison, ptr %phi8, align 1
  br label %bb15

bb11:                                             ; preds = %bb7
  br i1 poison, label %bb13, label %bb12

bb12:                                             ; preds = %bb11
  br label %bb13

bb13:                                             ; preds = %bb12, %bb11
  %getelementptr14 = getelementptr inbounds i8, ptr %phi8, i32 poison
  br label %bb15

bb15:                                             ; preds = %bb13, %bb9
  %phi16 = phi ptr [ %getelementptr14, %bb13 ], [ %getelementptr10, %bb9 ]
  br i1 poison, label %bb5, label %bb7

bb17:                                             ; preds = %bb5
  br label %bb1
}

Crash on wasm-ld (failed Received SIGSEGV (-11))

I came across this error when trying to build wasm artifact of [this repository](https://github.com/daquexian/onnx-simplifier) ( branch `v0.4.36` ) using ninja.

The `emsdk` version that I used was 3.1.72.

```
: && /home/yogisalomo/emsdk/upstream/emscripten/em++ -O3 -DNDEBUG -s ALLOW_MEMORY_GROWTH=1 -s EXIT_RUNTIME=1 -s FORCE_FILESYSTEM=1 -s MODULARIZE=1 -s 'EXPORT_NAME="create_onnxsim"' -s 'EXPORTED_RUNTIME_METHODS=[FS,ccall,cwrap,callMain]' -s EXPORTED_FUNCTIONS=[_main] CMakeFiles/onnxsim_bin.dir/onnxsim/bin/onnxsim_bin.cpp.o CMakeFiles/onnxsim_bin.dir/onnxsim/bin/onnxsim_option.cpp.o -o onnxsim.js  libonnxsim.a  third_party/onnx-optimizer/libonnx_optimizer.a  libonnxruntime_webassembly.a && :
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /home/yogisalomo/emsdk/upstream/bin/wasm-ld -o onnxsim.wasm -L/home/yogisalomo/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten CMakeFiles/onnxsim_bin.dir/onnxsim/bin/onnxsim_bin.cpp.o CMakeFiles/onnxsim_bin.dir/onnxsim/bin/onnxsim_option.cpp.o libonnxsim.a third_party/onnx-optimizer/libonnx_optimizer.a libonnxruntime_webassembly.a -lGL-getprocaddr -lal -lhtml5 -lstubs -lc -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /tmp/tmpuew4mr6alibemscripten_js_symbols.so --strip-debug --export=_emscripten_stack_alloc --export=__get_temp_ret --export=__set_temp_ret --export=__funcs_on_exit --export=__wasm_call_ctors --export=emscripten_stack_get_current --export=_emscripten_stack_restore --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --max-memory=2147483648 --initial-heap=16777216 --no-entry --table-base=1 --global-base=1024
1.      Running pass "cgscc(function-attrs)" on module "ld-temp.o"
 #0 0x00005a6692b63088 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x1083088)
 #1 0x00005a6692b603ee llvm::sys::RunSignalHandlers() (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x10803ee)
 #2 0x00005a6692b63c7f SignalHandler(int) Signals.cpp:0:0
 #3 0x000079f165242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00005a66941e9d3c checkFunctionMemoryAccess(llvm::Function&, bool, llvm::AAResults&, llvm::SmallSetVector<llvm::Function*, 8u> const&) (.llvm.13958950707188126733) FunctionAttrs.cpp:0:0
 #5 0x00005a66941eb09a llvm::SmallSet<llvm::Function*, 8u, std::__2::less<llvm::Function*>> deriveAttrsInPostOrder<llvm::PostOrderFunctionAttrsPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&)::$_0&>(llvm::ArrayRef<llvm::Function*>, llvm::PostOrderFunctionAttrsPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&)::$_0&, bool) FunctionAttrs.cpp:0:0
 #6 0x00005a66941ea819 llvm::PostOrderFunctionAttrsPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x270a819)
 #7 0x00005a6693a8370d llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PostOrderFunctionAttrsPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) PassBuilder.cpp:0:0
 #8 0x00005a6694de42f3 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x33042f3)
 #9 0x00005a6693a605fd llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilder.cpp:0:0
#10 0x00005a6695695c9a llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x3bb5c9a)
#11 0x00005a66939ba386 llvm::lto::opt(llvm::lto::Config const&, llvm::TargetMachine*, unsigned int, llvm::Module&, bool, llvm::ModuleSummaryIndex*, llvm::ModuleSummaryIndex const*, std::__2::vector<unsigned char, std::__2::allocator<unsigned char>> const&) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x1eda386)
#12 0x00005a66939bc7e3 llvm::lto::backend(llvm::lto::Config const&, std::__2::function<llvm::Expected<std::__2::unique_ptr<llvm::CachedFileStream, std::__2::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, unsigned int, llvm::Module&, llvm::ModuleSummaryIndex&) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x1edc7e3)
#13 0x00005a66939a602f llvm::lto::LTO::runRegularLTO(std::__2::function<llvm::Expected<std::__2::unique_ptr<llvm::CachedFileStream, std::__2::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x1ec602f)
#14 0x00005a66939a52ad llvm::lto::LTO::run(std::__2::function<llvm::Expected<std::__2::unique_ptr<llvm::CachedFileStream, std::__2::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, llvm::FileCache) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x1ec52ad)
#15 0x00005a6693014dd3 lld::wasm::BitcodeCompiler::compile() (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x1534dd3)
#16 0x00005a66930184b4 lld::wasm::SymbolTable::compileBitcodeFiles() (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x15384b4)
#17 0x00005a6692ffe90c lld::wasm::(anonymous namespace)::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) Driver.cpp:0:0
#18 0x00005a6692ff88f8 lld::wasm::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x15188f8)
#19 0x00005a6692b660f0 lld::unsafeLldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>, bool) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0x10860f0)
#20 0x00005a6692aa64d1 lld_main(int, char**, llvm::ToolContext const&) (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0xfc64d1)
#21 0x00005a6692aa6ec4 main (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0xfc6ec4)
#22 0x000079f165229d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#23 0x000079f165229e40 call_init ./csu/../csu/libc-start.c:128:20
#24 0x000079f165229e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#25 0x00005a6692a1336a _start (/home/yogisalomo/emsdk/upstream/bin/wasm-ld+0xf3336a)
em++: error: '/home/yogisalomo/emsdk/upstream/bin/wasm-ld -o onnxsim.wasm -L/home/yogisalomo/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten CMakeFiles/onnxsim_bin.dir/onnxsim/bin/onnxsim_bin.cpp.o CMakeFiles/onnxsim_bin.dir/onnxsim/bin/onnxsim_option.cpp.o libonnxsim.a third_party/onnx-optimizer/libonnx_optimizer.a libonnxruntime_webassembly.a -lGL-getprocaddr -lal -lhtml5 -lstubs -lc -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /tmp/tmpuew4mr6alibemscripten_js_symbols.so --strip-debug --export=_emscripten_stack_alloc --export=__get_temp_ret --export=__set_temp_ret --export=__funcs_on_exit --export=__wasm_call_ctors --export=emscripten_stack_get_current --export=_emscripten_stack_restore --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --max-memory=2147483648 --initial-heap=16777216 --no-entry --table-base=1 --global-base=1024' failed (received SIGSEGV (-11))
ninja: build stopped: subcommand failed.
```

Please let me know if there's any other detail that I need to add to help solving this issue. Thank you.

How can I reproduce it? I can't find any instructions in that repo. I cloned the repo and ran `./build_wasm.sh`, but it says
```console
aheejin@aheejin:~/test/onnx-simplifier$ ./build_wasm.sh
+ command -v emcmake
+++ dirname -- ./build_wasm.sh
++ cd -- .
++ pwd
+ SCRIPT_DIR=/usr/local/google/home/aheejin/test/onnx-simplifier
+ WITH_NODE_RAW_FS=OFF
+ cd /usr/local/google/home/aheejin/test/onnx-simplifier
+ pushd third_party/onnxruntime/cmake/external/protobuf/cmake
./build_wasm.sh: line 11: pushd: third_party/onnxruntime/cmake/external/protobuf/cmake: No such file or directory
```

@aheejin thank you for responding. From the error message, seems like you didn't clone the repository recursively and therefore missing the files of the third_party repositories. Can you please try that?

Sorry for the long wait! In case you use emscripten releases, 4.0.1 release contains the fix: https://github.com/emscripten-core/emsdk/releases/tag/4.0.1


commit 4b5018d2311596778cade4db5177e2ab879cc218
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Oct 10 13:40:22 2024 -0700

    [SLP]Track repeated reduced value as it might be vectorized

    Need to track changes with the repeated reduced value, since it might be
    vectorized in the next attempt for reduction vectorization, to correctly
    generate the code and avoid compiler crash.

    Fixes #111887

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 94de520a2715..e2958c49b8ca 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -1293,8 +1293,7 @@ public:
   using InstrList = SmallVector<Instruction *, 16>;
   using ValueSet = SmallPtrSet<Value *, 16>;
   using StoreList = SmallVector<StoreInst *, 8>;
-  using ExtraValueToDebugLocsMap =
-      MapVector<Value *, SmallVector<Instruction *, 2>>;
+  using ExtraValueToDebugLocsMap = SmallDenseSet<Value *, 4>;
   using OrdersType = SmallVector<unsigned, 4>;

   BoUpSLP(Function *Func, ScalarEvolution *Se, TargetTransformInfo *Tti,
@@ -6322,7 +6321,7 @@ void BoUpSLP::buildExternalUses(
         continue;

       // Check if the scalar is externally used as an extra arg.
-      const auto *ExtI = ExternallyUsedValues.find(Scalar);
+      const auto ExtI = ExternallyUsedValues.find(Scalar);
       if (ExtI != ExternallyUsedValues.end()) {
         int FoundLane = Entry->findLaneForValue(Scalar);
         LLVM_DEBUG(dbgs() << "SLP: Need to extract: Extra arg from lane "
@@ -18820,7 +18819,7 @@ public:
     // List of the values that were reduced in other trees as part of gather
     // nodes and thus requiring extract if fully vectorized in other trees.
     SmallPtrSet<Value *, 4> RequiredExtract;
-    Value *VectorizedTree = nullptr;
+    WeakTrackingVH VectorizedTree = nullptr;
     bool CheckForReusedReductionOps = false;
     // Try to vectorize elements based on their type.
     SmallVector<InstructionsState> States;
@@ -18916,6 +18915,7 @@ public:
       bool SameScaleFactor = false;
       bool OptReusedScalars = IsSupportedHorRdxIdentityOp &&
                               SameValuesCounter.size() != Candidates.size();
+      BoUpSLP::ExtraValueToDebugLocsMap ExternallyUsedValues;
       if (OptReusedScalars) {
         SameScaleFactor =
             (RdxKind == RecurKind::Add || RdxKind == RecurKind::FAdd ||
@@ -18936,6 +18936,7 @@ public:
               emitScaleForReusedOps(Candidates.front(), Builder, Cnt);
           VectorizedTree = GetNewVectorizedTree(VectorizedTree, RedVal);
           VectorizedVals.try_emplace(OrigV, Cnt);
+          ExternallyUsedValues.insert(OrigV);
           continue;
         }
       }
@@ -19015,17 +19016,18 @@ public:
         V.reorderBottomToTop(/*IgnoreReorder=*/true);
         // Keep extracted other reduction values, if they are used in the
         // vectorization trees.
-        BoUpSLP::ExtraValueToDebugLocsMap LocalExternallyUsedValues;
+        BoUpSLP::ExtraValueToDebugLocsMap LocalExternallyUsedValues(
+            ExternallyUsedValues);
         // The reduction root is used as the insertion point for new
         // instructions, so set it as externally used to prevent it from being
         // deleted.
-        LocalExternallyUsedValues[ReductionRoot];
+        LocalExternallyUsedValues.insert(ReductionRoot);
         for (unsigned Cnt = 0, Sz = ReducedVals.size(); Cnt < Sz; ++Cnt) {
           if (Cnt == I || (ShuffledExtracts && Cnt == I - 1))
             continue;
           for (Value *V : ReducedVals[Cnt])
             if (isa<Instruction>(V))
-              LocalExternallyUsedValues[TrackedVals[V]];
+              LocalExternallyUsedValues.insert(TrackedVals[V]);
         }
         if (!IsSupportedHorRdxIdentityOp) {
           // Number of uses of the candidates in the vector of values.
@@ -19054,21 +19056,21 @@ public:
           // Check if the scalar was vectorized as part of the vectorization
           // tree but not the top node.
           if (!VLScalars.contains(RdxVal) && V.isVectorized(RdxVal)) {
-            LocalExternallyUsedValues[RdxVal];
+            LocalExternallyUsedValues.insert(RdxVal);
             continue;
           }
           Value *OrigV = TrackedToOrig.at(RdxVal);
           unsigned NumOps =
               VectorizedVals.lookup(OrigV) + At(SameValuesCounter, OrigV);
           if (NumOps != ReducedValsToOps.at(OrigV).size())
-            LocalExternallyUsedValues[RdxVal];
+            LocalExternallyUsedValues.insert(RdxVal);
         }
         // Do not need the list of reused scalars in regular mode anymore.
         if (!IsSupportedHorRdxIdentityOp)
           SameValuesCounter.clear();
         for (Value *RdxVal : VL)
           if (RequiredExtract.contains(RdxVal))
-            LocalExternallyUsedValues[RdxVal];
+            LocalExternallyUsedValues.insert(RdxVal);
         V.buildExternalUses(LocalExternallyUsedValues);

         V.computeMinimumValueSizes();

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

define void @test() {
entry:
  %0 = load i16, ptr null, align 2
  %1 = xor i16 %0, 0
  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 %0)
  %3 = tail call i16 @llvm.smax.i16(i16 0, i16 %2)
  %4 = load i16, ptr getelementptr inbounds (i8, ptr null, i64 6), align 2
  %5 = xor i16 %4, 0
  %6 = tail call i16 @llvm.smax.i16(i16 %5, i16 %0)
  %7 = tail call i16 @llvm.smax.i16(i16 %3, i16 %6)
  %8 = load i16, ptr getelementptr (i8, ptr null, i64 12), align 2
  %9 = xor i16 %8, 0
  %10 = tail call i16 @llvm.smax.i16(i16 %9, i16 %0)
  %11 = tail call i16 @llvm.smax.i16(i16 %7, i16 %10)
  %12 = load i16, ptr getelementptr (i8, ptr null, i64 18), align 2
  %13 = xor i16 %12, 0
  %14 = tail call i16 @llvm.smax.i16(i16 %13, i16 %0)
  %15 = tail call i16 @llvm.smax.i16(i16 %11, i16 %14)
  %16 = tail call i16 @llvm.smax.i16(i16 %15, i16 0)
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i16 @llvm.smax.i16(i16, i16) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

[SLP-Vectorizer] Segfault in `HorizontalReduction::matchAssociativeReduction`

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

define i32 @main() #0 {
for.body.preheader:
  %0 = load i16, ptr null, align 2
  %1 = xor i16 %0, 0
  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 %0)
  %3 = tail call i16 @llvm.smax.i16(i16 0, i16 %2)
  %4 = load i16, ptr getelementptr inbounds (i8, ptr null, i64 6), align 2
  %5 = xor i16 %4, 0
  %6 = tail call i16 @llvm.smax.i16(i16 %5, i16 %0)
  %7 = tail call i16 @llvm.smax.i16(i16 %3, i16 %6)
  %8 = load i16, ptr getelementptr (i8, ptr null, i64 12), align 2
  %9 = xor i16 %8, 0
  %10 = tail call i16 @llvm.smax.i16(i16 %9, i16 %0)
  %11 = tail call i16 @llvm.smax.i16(i16 %7, i16 %10)
  %12 = load i16, ptr getelementptr (i8, ptr null, i64 18), align 2
  %13 = xor i16 %12, 0
  %14 = tail call i16 @llvm.smax.i16(i16 %13, i16 %0)
  %15 = tail call i16 @llvm.smax.i16(i16 %11, i16 %14)
  %16 = tail call i16 @llvm.smax.i16(i16 %15, i16 0)
  ret i32 0
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i16 @llvm.smax.i16(i16, i16) #1

; uselistorder directives
uselistorder ptr null, { 3, 2, 1, 0 }
uselistorder ptr @llvm.smax.i16, { 8, 7, 6, 5, 4, 3, 2, 1, 0 }

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-b,-e,-experimental-smctr,-experimental-smmpm,-experimental-smnpm,-experimental-ssctr,-experimental-ssnpm,-experimental-sspm,-experimental-supm,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-h,-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,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-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,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
```

Command/backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=slp-vectorizer reduced.ll
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.

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 reduced.ll
1.      Running pass "function(slp-vectorizer)" on module "reduced.ll"
2.      Running pass "slp-vectorizer" on function "main"
 #0 0x0000602da32b35e0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x30fe5e0)
 #1 0x0000602da32b09ef llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x30fb9ef)
 #2 0x0000602da32b0b45 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007ea045842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x0000602da29cea64 llvm::getUnderlyingObject(llvm::Value const*, unsigned int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2819a64)
 #5 0x0000602da22d706d (anonymous namespace)::HorizontalReduction::matchAssociativeReduction(llvm::slpvectorizer::BoUpSLP&, llvm::Instruction*, llvm::ScalarEvolution&, llvm::DataLayout const&, llvm::TargetLibraryInfo const&)::'lambda0'(unsigned long, llvm::LoadInst*)::operator()(unsigned long, llvm::LoadInst*) const SLPVectorizer.cpp:0:0
 #6 0x0000602da22d797e generateKeySubkey(llvm::Value*, llvm::TargetLibraryInfo const*, llvm::function_ref<llvm::hash_code (unsigned long, llvm::LoadInst*)>, bool) (.constprop.0) SLPVectorizer.cpp:0:0
 #7 0x0000602da230d085 (anonymous namespace)::HorizontalReduction::matchAssociativeReduction(llvm::slpvectorizer::BoUpSLP&, llvm::Instruction*, llvm::ScalarEvolution&, llvm::DataLayout const&, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
 #8 0x0000602da231f7cc 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+0x216a7cc)
 #9 0x0000602da2323ec2 llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*) (.constprop.0) SLPVectorizer.cpp:0:0
#10 0x0000602da2327dfb llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2172dfb)
#11 0x0000602da232e400 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
#12 0x0000602da232ef62 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2179f62)
#13 0x0000602da1071366 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+0xebc366)
#14 0x0000602da30bc88f 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+0x2f0788f)
#15 0x0000602da1073bb6 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+0xebebb6)
#16 0x0000602da30bac1b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f05c1b)
#17 0x0000602da106fcc6 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+0xebacc6)
#18 0x0000602da30bb77d 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+0x2f0677d)
#19 0x0000602da088061b 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+0x6cb61b)
#20 0x0000602da0872331 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6bd331)
#21 0x00007ea045829d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#22 0x00007ea045829e40 call_init ./csu/../csu/libc-start.c:128:20
#23 0x00007ea045829e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#24 0x0000602da0868855 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6b3855)
zsh: segmentation fault (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Godbolt: https://godbolt.org/z/nbar8q6ej

Found via fuzzer (C program before reduction).


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();

opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s

[SLPVectorizer] Assertion `OpIdx < Operands.size() && "Off bounds"' failed.

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


commit 066b88879ab5c195e7e14609e546cc238c2f3bf3
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Jan 13 10:51:26 2025 -0800

    [SLP]Correctly set vector operand for extracts with poisons

    When extracts are vectorized and it has some poison values instead of
    instructions, need to correctly set the vectorized operand not as
    poison, but as a main vector operand of the main extract instruction.

    Fixes #122583

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 4b0ed5b30179..2742c3777c1e 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -2441,6 +2441,17 @@ public:
           // operations or alternating sequences (e.g., +, -), we can safely
           // tell the inverse operations by checking commutativity.
           if (isa<PoisonValue>(VL[Lane])) {
+            if (auto *EI = dyn_cast<ExtractElementInst>(VL0)) {
+              if (OpIdx == 0) {
+                OpsVec[OpIdx][Lane] = {EI->getVectorOperand(), true, false};
+                continue;
+              }
+            } else if (auto *EV = dyn_cast<ExtractValueInst>(VL0)) {
+              if (OpIdx == 0) {
+                OpsVec[OpIdx][Lane] = {EV->getAggregateOperand(), true, false};
+                continue;
+              }
+            }
             OpsVec[OpIdx][Lane] = {
                 PoisonValue::get(VL0->getOperand(OpIdx)->getType()), true,
                 false};

[SLPVectorizer] Miscompilation

Reproducer: https://godbolt.org/z/7eEEeeKoo
Sorry, I cannot provide alive2 link since `llvm.vector.insert.v8i64.v4i64` is not supported.
```
; bin/opt -passes=slp-vectorizer reduced.ll -S -o opt.ll

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"

@j = global [4 x i64] zeroinitializer

define i32 @main() {
entry:
  %.pre.i = load i64, ptr getelementptr inbounds nuw (i8, ptr @j, i64 24), align 8
  %.pre50.i = load i64, ptr getelementptr inbounds nuw (i8, ptr @j, i64 16), align 16
  %.pre51.i = load i64, ptr getelementptr inbounds nuw (i8, ptr @j, i64 8), align 8
  %.pre52.i = load i64, ptr @j, align 16
  %0 = or i64 %.pre51.i, 0
  %1 = trunc i64 %.pre.i to i32
  %2 = add i32 %1, 0
  %3 = trunc i64 %.pre50.i to i32
  %4 = add i32 %3, 0
  %5 = trunc i64 %.pre51.i to i32
  %6 = add i32 %5, 0
  %7 = trunc i64 0 to i32
  %8 = add i32 %5, 0
  %9 = add i32 %7, 0
  %10 = add i32 %1, 0
  %11 = add i32 %3, 0
  %12 = add i32 %5, 0
  %13 = add i32 %7, 0
  %14 = trunc i64 %.pre.i to i32
  %15 = add i32 %14, 0
  %16 = trunc i64 %.pre50.i to i32
  %17 = add i32 %16, 0
  %18 = trunc i64 %.pre51.i to i32
  %19 = add i32 %18, 0
  %20 = trunc i64 %.pre52.i to i32
  %conv14.1.i = or i32 %9, %13
  %21 = or i32 %conv14.1.i, %6
  %22 = or i32 %21, %8
  %23 = or i32 %22, %12
  %24 = or i32 %23, %4
  %25 = or i32 %24, %11
  %26 = or i32 %25, %2
  %27 = or i32 %26, %10
  %28 = or i32 %27, %15
  %29 = or i32 %28, %17
  %30 = or i32 %29, %19
  %31 = add i32 %14, 0
  %32 = add i32 %16, 0
  %33 = add i32 %18, 0
  %34 = add i32 %20, 0
  %35 = add i32 %14, 0
  %36 = add i32 %16, 0
  %37 = add i32 %18, 0
  %38 = add i32 %20, 0
  %39 = add i32 %14, 0
  %40 = add i32 %16, 0
  %41 = add i32 %18, 0
  %42 = add i32 %20, 0
  %inc.3.3.i.1 = or i64 %.pre52.i, 0
  %conv14.i.1 = or i32 %38, %34
  %conv14.1.i.1 = or i32 %conv14.i.1, %42
  %conv14.3.i.1 = or i32 %conv14.1.i.1, %33
  %conv14.145.i.1 = or i32 %conv14.3.i.1, %37
  %conv14.1.1.i.1 = or i32 %conv14.145.i.1, %41
  %conv14.3.1.i.1 = or i32 %conv14.1.1.i.1, %32
  %conv14.247.i.1 = or i32 %conv14.3.1.i.1, %36
  %conv14.1.2.i.1 = or i32 %conv14.247.i.1, %40
  %conv14.3.2.i.1 = or i32 %conv14.1.2.i.1, %31
  %conv14.349.i.1 = or i32 %conv14.3.2.i.1, %35
  %conv14.1.3.i.1 = or i32 %conv14.349.i.1, %39
  %conv14.3.3.i.1 = or i32 %conv14.1.3.i.1, %30
  ret i32 %conv14.3.3.i.1
}
```
Output:
```
source_filename = "/app/example.ll"
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 i32 @main() {
  %0 = load <4 x i64>, ptr @j, align 16
  %1 = or i64 poison, 0
  %2 = shufflevector <4 x i64> %0, <4 x i64> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 1, i32 poison, i32 poison>
  %3 = shufflevector <4 x i64> %0, <4 x i64> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
  %4 = shufflevector <8 x i64> %3, <8 x i64> <i64 poison, i64 poison, i64 poison, i64 poison, i64 0, i64 poison, i64 poison, i64 poison>, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 12, i32 1, i32 poison, i32 poison>
  %5 = call <8 x i64> @llvm.vector.insert.v8i64.v4i64(<8 x i64> %4, <4 x i64> %0, i64 0)
  %6 = trunc <8 x i64> %5 to <8 x i32>
  %7 = shufflevector <8 x i32> %6, <8 x i32> poison, <16 x i32> <i32 0, i32 0, i32 0, i32 1, i32 1, i32 1, i32 2, i32 2, i32 2, i32 3, i32 3, i32 3, i32 4, i32 4, i32 5, i32 5>
  %8 = add <16 x i32> %7, zeroinitializer
  %9 = extractelement <4 x i64> %0, i32 0
  %inc.3.3.i.1 = or i64 %9, 0
  %10 = call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> %8)
  %11 = call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> poison)
  %op.rdx = or i32 %10, %11
  ret i32 %op.rdx
}

declare <8 x i64> @llvm.vector.insert.v8i64.v4i64(<8 x i64>, <4 x i64>, i64 immarg) #0

declare i32 @llvm.vector.reduce.or.v16i32(<16 x i32>) #0

declare i32 @llvm.vector.reduce.or.v8i32(<8 x i32>) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
```
lli output:
```
> bin/lli reduced.ll
> echo $?
0
> bin/lli opt.ll
> echo $?
255
```
[llubi](https://github.com/dtcxzyw/llvm-ub-aware-interpreter) output:
Before:
```
> ./llubi reduced.ll --verbose
Entering function main
  %0 = getelementptr inbounds nuw i8, ptr @j, i64 24 -> Ptr 40[@j + 24]
  %.pre.i = load i64, ptr %0, align 8 -> i64 0
  %1 = getelementptr inbounds nuw i8, ptr @j, i64 16 -> Ptr 32[@j + 16]
  %.pre50.i = load i64, ptr %1, align 16 -> i64 0
  %2 = getelementptr inbounds nuw i8, ptr @j, i64 8 -> Ptr 24[@j + 8]
  %.pre51.i = load i64, ptr %2, align 8 -> i64 0
  %.pre52.i = load i64, ptr @j, align 16 -> i64 0
  %3 = or i64 %.pre51.i, 0 -> i64 0
  %4 = trunc i64 %.pre.i to i32 -> i32 0
  %5 = add i32 %4, 0 -> i32 0
  %6 = trunc i64 %.pre50.i to i32 -> i32 0
  %7 = add i32 %6, 0 -> i32 0
  %8 = trunc i64 %.pre51.i to i32 -> i32 0
  %9 = add i32 %8, 0 -> i32 0
  %10 = trunc i64 0 to i32 -> i32 0
  %11 = add i32 %8, 0 -> i32 0
  %12 = add i32 %10, 0 -> i32 0
  %13 = add i32 %4, 0 -> i32 0
  %14 = add i32 %6, 0 -> i32 0
  %15 = add i32 %8, 0 -> i32 0
  %16 = add i32 %10, 0 -> i32 0
  %17 = trunc i64 %.pre.i to i32 -> i32 0
  %18 = add i32 %17, 0 -> i32 0
  %19 = trunc i64 %.pre50.i to i32 -> i32 0
  %20 = add i32 %19, 0 -> i32 0
  %21 = trunc i64 %.pre51.i to i32 -> i32 0
  %22 = add i32 %21, 0 -> i32 0
  %23 = trunc i64 %.pre52.i to i32 -> i32 0
  %conv14.1.i = or i32 %12, %16 -> i32 0
  %24 = or i32 %conv14.1.i, %9 -> i32 0
  %25 = or i32 %24, %11 -> i32 0
  %26 = or i32 %25, %15 -> i32 0
  %27 = or i32 %26, %7 -> i32 0
  %28 = or i32 %27, %14 -> i32 0
  %29 = or i32 %28, %5 -> i32 0
  %30 = or i32 %29, %13 -> i32 0
  %31 = or i32 %30, %18 -> i32 0
  %32 = or i32 %31, %20 -> i32 0
  %33 = or i32 %32, %22 -> i32 0
  %34 = add i32 %17, 0 -> i32 0
  %35 = add i32 %19, 0 -> i32 0
  %36 = add i32 %21, 0 -> i32 0
  %37 = add i32 %23, 0 -> i32 0
  %38 = add i32 %17, 0 -> i32 0
  %39 = add i32 %19, 0 -> i32 0
  %40 = add i32 %21, 0 -> i32 0
  %41 = add i32 %23, 0 -> i32 0
  %42 = add i32 %17, 0 -> i32 0
  %43 = add i32 %19, 0 -> i32 0
  %44 = add i32 %21, 0 -> i32 0
  %45 = add i32 %23, 0 -> i32 0
  %inc.3.3.i.1 = or i64 %.pre52.i, 0 -> i64 0
  %conv14.i.1 = or i32 %41, %37 -> i32 0
  %conv14.1.i.1 = or i32 %conv14.i.1, %45 -> i32 0
  %conv14.3.i.1 = or i32 %conv14.1.i.1, %36 -> i32 0
  %conv14.145.i.1 = or i32 %conv14.3.i.1, %40 -> i32 0
  %conv14.1.1.i.1 = or i32 %conv14.145.i.1, %44 -> i32 0
  %conv14.3.1.i.1 = or i32 %conv14.1.1.i.1, %35 -> i32 0
  %conv14.247.i.1 = or i32 %conv14.3.1.i.1, %39 -> i32 0
  %conv14.1.2.i.1 = or i32 %conv14.247.i.1, %43 -> i32 0
  %conv14.3.2.i.1 = or i32 %conv14.1.2.i.1, %34 -> i32 0
  %conv14.349.i.1 = or i32 %conv14.3.2.i.1, %38 -> i32 0
  %conv14.1.3.i.1 = or i32 %conv14.349.i.1, %42 -> i32 0
  %conv14.3.3.i.1 = or i32 %conv14.1.3.i.1, %33 -> i32 0
  ret i32 %conv14.3.3.i.1
Exiting function main
```
After:
```
> ./llubi opt.ll --verbose
Entering function main
  %0 = load <4 x i64>, ptr @j, align 16 -> { i64 0, i64 0, i64 0, i64 0 }
  %1 = or i64 poison, 1 -> poison
  %2 = or i64 poison, 0 -> poison
  %3 = shufflevector <4 x i64> %0, <4 x i64> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 1, i32 poison, i32 poison> -> { poison, poison, poison, poison, poison, i64 0, poison, poison }
  %4 = shufflevector <4 x i64> %0, <4 x i64> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison> -> { i64 0, i64 0, i64 0, i64 0, poison, poison, poison, poison }
  %5 = shufflevector <8 x i64> %4, <8 x i64> <i64 poison, i64 poison, i64 poison, i64 poison, i64 0, i64 poison, i64 poison, i64 poison>, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 12, i32 1, i32 poison, i32 poison> -> { poison, poison, poison, poison, i64 0, i64 0, poison, poison }
  %6 = call <8 x i64> @llvm.vector.insert.v8i64.v4i64(<8 x i64> %5, <4 x i64> %0, i64 0) -> { i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, poison, poison }
  %7 = trunc <8 x i64> %6 to <8 x i32> -> { i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, poison, poison }
  %8 = shufflevector <8 x i32> %7, <8 x i32> poison, <16 x i32> <i32 0, i32 0, i32 0, i32 1, i32 1, i32 1, i32 2, i32 2, i32 2, i32 3, i32 3, i32 3, i32 4, i32 4, i32 5, i32 5> -> { i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0 }
  %9 = add <16 x i32> %8, zeroinitializer -> { i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0 }
  %10 = extractelement <4 x i64> %0, i32 0 -> i64 0
  %inc.3.3.i.1 = or i64 %10, 0 -> i64 0
  %11 = call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> %9) -> i32 0
  %12 = call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> poison) -> poison
  %op.rdx = or i32 %11, %12 -> poison
  ret i32 %op.rdx
Exiting function main

UB triggered: Return a poison value
Exited with immediate UB.
Stacktrace:
```

miscompilation
llvm:SLPVectorizer
generated by fuzzer

llvm version: 6329355860e9b66bc7ed68b46c166763e408d4cc


commit 144bdf3eb7128518ed162c5a168e3ec90922cd9e
Author: Florian Hahn <flo@fhahn.com>
Date:   Fri Nov 8 20:53:03 2024 +0000

    [VPlan] Also check if plan for best legacy VF contains simplifications.

    The plan for the VF chosen by the legacy cost model could also contain
    additional simplifications that cause cost differences. Also check if it
    contains simplifications.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index c07af8519049..82d85b112397 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7521,6 +7521,8 @@ VectorizationFactor LoopVectorizationPlanner::computeBestVF() {
   precomputeCosts(BestPlan, BestFactor.Width, CostCtx);
   assert((BestFactor.Width == LegacyVF.Width ||
           planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width),
+                                                CostCtx, OrigLoop) ||
+          planContainsAdditionalSimplifications(getPlanFor(LegacyVF.Width),
                                                 CostCtx, OrigLoop)) &&
          " VPlan cost model and legacy cost model disagreed");
   assert((BestFactor.Width.isScalar() || BestFactor.ScalarCost > 0) &&

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @test_invariant_cond_for_select(ptr %dst, i8 %x) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %c.1 = icmp eq i8 %x, 0
  %c.2 = icmp sgt i64 %iv, 0
  %c.2.ext = zext i1 %c.2 to i64
  %sel = select i1 %c.1, i64 %c.2.ext, i64 0
  %sel.trunc = trunc i64 %sel to i8
  %gep = getelementptr inbounds i8, ptr %dst, i64 %iv
  store i8 %sel.trunc, ptr %gep, align 1
  %iv.next = add i64 %iv, 4
  %ec = icmp ult i64 %iv, 14
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-features"="+64bit,+v" }

[VPlan] Assertion " VPlan cost model and legacy cost model disagreed"' failed.

Testcase:
```c
extern char a[];
char *b;
int c = 40502824327348188;
long d[9][9];
int main() {
  for (long e = 0; e < 9; ++e)
    for (long f = 0; f < 9; ++f)
      d[e][f] = 6032102684657866;
  for (unsigned char f = b[4]; f < 18; f += c - 216)
    a[f] = f % 2 ? d[f][f] : d[f][f] + 2036854775807 > 0;
}
```
```
/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/clang -I/scratch/tc-testing/compiler-fuzz-ci/csmith-build/include -fsigned-char -fno-strict-aliasing -fwrapv -march=rv64gcv -flto -O3 -fuse-ld=lld red.c -o rv64gcv.out
```

Reduced 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 i32 @main() #0 {
entry:
  br label %for.body15

for.cond.cleanup14.loopexit:                      ; preds = %for.body15
  ret i32 0

for.body15:                                       ; preds = %for.body15, %entry
  %indvars.iv1 = phi i64 [ %indvars.iv.next, %for.body15 ], [ 0, %entry ]
  %tobool.not = icmp eq i8 0, 0
  %cmp24 = icmp sgt i64 %indvars.iv1, 0
  %conv26 = zext i1 %cmp24 to i64
  %cond = select i1 %tobool.not, i64 %conv26, i64 0
  %conv27 = trunc i64 %cond to i8
  store i8 %conv27, ptr null, align 1
  %indvars.iv.next = add i64 %indvars.iv1, 4
  %cmp12 = icmp ult i64 %indvars.iv1, 14
  br i1 %cmp12, label %for.body15, label %for.cond.cleanup14.loopexit
}

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-b,-e,-experimental-smctr,-experimental-ssctr,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-h,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-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,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
```

Command/backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt --passes "loop-vectorize" reduced.ll -f
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7519: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' 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 loop-vectorize reduced.ll -f
1.      Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "reduced.ll"
2.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x00005f3d9fc9dc00 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x3169c00)
 #1 0x00005f3d9fc9b00f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x316700f)
 #2 0x00005f3d9fc9b165 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007abb28242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007abb282969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007abb282969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007abb282969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007abb28242476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007abb282287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007abb2822871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007abb28239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00005f3d9ebfb878 llvm::LoopVectorizationPlanner::computeBestVF() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20c7878)
#12 0x00005f3d9ec12dec llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20dedec)
#13 0x00005f3d9ec15f01 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20e1f01)
#14 0x00005f3d9ec16577 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20e2577)
#15 0x00005f3d9da0cba6 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, 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+0xed8ba6)
#16 0x00005f3d9faa518f 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+0x2f7118f)
#17 0x00005f3d9da0fdd6 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+0xedbdd6)
#18 0x00005f3d9faa351b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f6f51b)
#19 0x00005f3d9da0bc66 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+0xed7c66)
#20 0x00005f3d9faa407d 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+0x2f7007d)
#21 0x00005f3d9d20ca8d 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+0x6d8a8d)
#22 0x00005f3d9d1fe911 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6ca911)
#23 0x00007abb28229d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#24 0x00007abb28229e40 call_init ./csu/../csu/libc-start.c:128:20
#25 0x00007abb28229e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#26 0x00005f3d9d1f4e65 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6c0e65)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Found via fuzzer on Oct 24th

Godbolt: https://godbolt.org/z/zhseEjTso

cc @fhahn