Bug type: miscompilation
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::vectorizeTree
Issue title: wrong code at -O3 on x86_64-linux-gnu
Labels: miscompilation
llvm:SLPVectorizer
confirmed
Reported by: zhendongsu

It appears to be a recent regression as it doesn't reproduce with 18.1.0 and earlier. 

Compiler Explorer: https://godbolt.org/z/fzsqjEPWW

```
[562] % clangtk -v
clang version 19.0.0git (https://github.com/llvm/llvm-project.git 52139d8f9a4e3f595ca552393d62ba06b0bc082c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[563] % 
[563] % clangtk -O2 -w small.c
[564] % ./a.out
0
[565] % clangtk -O3 -w small.c
[566] % ./a.out
[567] % 
[567] % cat small.c
int printf(const char *, ...);
int a, b, e, g;
volatile int c;
static int d[1] = {1}, f;
int h() {
  for (b = 0; b < 4; b++) {
    for (e = 0; e < 4; e++)
      while (b) {
        if (c > 0 && d[1])
          break;
        return f;
      }
  }
  return 0;
}
void i() {
  int *j[1];
  j[g] = &d[0];
}
int main() {
  h();
  printf("%d\n", a);
  return 0;
}
```



Comments: author: dtcxzyw
body: Reproducer: https://alive2.llvm.org/ce/z/Whfr_a
```
; bin/opt -passes=slp-vectorizer -S test.ll
define i1 @src(i1 %cmp4.118.i) {
  %cmp4.118.i.not = xor i1 %cmp4.118.i, true
  %brmerge = select i1 %cmp4.118.i.not, i1 true, i1 poison
  %.not = xor i1 poison, true
  %brmerge2 = select i1 %brmerge, i1 true, i1 %.not
  %.not3 = xor i1 poison, true
  %brmerge4 = select i1 %brmerge2, i1 true, i1 %.not3
  %.not5 = xor i1 poison, true
  %brmerge6 = select i1 %brmerge4, i1 true, i1 %.not5
  %.not7 = xor i1 poison, true
  %brmerge8 = select i1 %brmerge6, i1 true, i1 %.not7
  ret i1 %brmerge8
}
```
```
define i1 @tgt(i1 %cmp4.118.i) {
  %1 = insertelement <4 x i1> <i1 poison, i1 true, i1 true, i1 true>, i1 %cmp4.118.i, i32 0
  %2 = xor <4 x i1> %1, <i1 true, i1 poison, i1 poison, i1 poison>
  %.not7 = xor i1 poison, true
  %3 = freeze <4 x i1> %2
  %4 = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %3)
  %op.rdx = select i1 %4, i1 true, i1 %.not7
  %op.rdx1 = select i1 poison, i1 true, i1 %op.rdx
  ret i1 %op.rdx1
}
```
cc @alexey-bataev 

Fix patch:
commit beccecaacde405a3b50891c67594eccbcd1c8b08
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Jul 15 07:03:22 2024 -0700

    [SLP]Fix PR98838: do no replace condition of select-based logical op by poison.
    
    If the reduction operation is a select-based logical op, the condition
    should be replaced by the poison, better to replace by the non-poisoning
    constant to prevent poison propagation in the vector code.
    
    Fixes https://github.com/llvm/llvm-project/issues/98838

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 5c2fc0b9320e..74a16d3fbcad 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -14201,9 +14201,23 @@ Value *BoUpSLP::vectorizeTree(
     for (Instruction *I : RemovedInsts) {
       if (getTreeEntry(I)->Idx != 0)
         continue;
+      SmallVector<SelectInst *> LogicalOpSelects;
       I->replaceUsesWithIf(PoisonValue::get(I->getType()), [&](Use &U) {
+        // Do not replace condition of the logical op in form select <cond>.
+        bool IsPoisoningLogicalOp = isa<SelectInst>(U.getUser()) &&
+                                    (match(U.getUser(), m_LogicalAnd()) ||
+                                     match(U.getUser(), m_LogicalOr())) &&
+                                    U.getOperandNo() == 0;
+        if (IsPoisoningLogicalOp) {
+          LogicalOpSelects.push_back(cast<SelectInst>(U.getUser()));
+          return false;
+        }
         return UserIgnoreList->contains(U.getUser());
       });
+      // Replace conditions of the poisoning logical ops with the non-poison
+      // constant value.
+      for (SelectInst *SI : LogicalOpSelects)
+        SI->setCondition(Constant::getNullValue(SI->getCondition()->getType()));
     }
   }
   // Retain to-be-deleted instructions for some debug-info bookkeeping and alias


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/select-reduction-op.ll
commands: opt -S --passes=slp-vectorizer < %s
tests: test_name: src
test_body: define i1 @src(i1 %cmp4.118.i) {
  %cmp4.118.i.not = xor i1 %cmp4.118.i, true
  %brmerge = select i1 %cmp4.118.i.not, i1 true, i1 poison
  %.not = xor i1 poison, true
  %brmerge2 = select i1 %brmerge, i1 true, i1 %.not
  %.not3 = xor i1 poison, true
  %brmerge4 = select i1 %brmerge2, i1 true, i1 %.not3
  %.not5 = xor i1 poison, true
  %brmerge6 = select i1 %brmerge4, i1 true, i1 %.not5
  %.not7 = xor i1 poison, true
  %brmerge8 = select i1 %brmerge6, i1 true, i1 %.not7
  ret i1 %brmerge8
}