Bug type: miscompilation
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::computeMinimumValueSizes
Issue title: [SLPVectorizer] Miscompile at O3
Labels: miscompilation
llvm:SLPVectorizer
Reported by: dtcxzyw

Reproducer: https://gist.github.com/dtcxzyw/117dc735db97658ea852d30fd896242a
```console
> bin/clang -O0 test.c -w -I/usr/include/csmith && ./a.out
checksum = BDCB7A78
> bin/clang -O3 test.c -w -mllvm -inline-threshold=100000 -I/usr/include/csmith && ./a.out
checksum = 9198FC41
```

llvm version: 1193f7d6487d2d94009f8d8d27da3907136482b9


Comments: author: dtcxzyw
body: Reproducer: https://alive2.llvm.org/ce/z/GCXoe9
```
; bin/opt -passes=slp-vectorizer test.ll -S

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define i1 @main(i32 %g.promoted.i.i, i16 %d.promoted.i.i) {
entry:
  %0 = and i16 %d.promoted.i.i, 1
  %xor.i.i = xor i32 %g.promoted.i.i, 1
  %conv1.i.i = trunc i32 %xor.i.i to i8
  %notsub.i = add i8 %conv1.i.i, -1
  %cmp.i.i = icmp sgt i8 %notsub.i, -3
  %conv3.i.i = zext i1 %cmp.i.i to i32
  %cmp4.i.i = icmp sgt i32 %xor.i.i, %conv3.i.i
  %conv1.1.i.i = trunc i32 %g.promoted.i.i to i8
  %notsub25.i = add i8 %conv1.1.i.i, -1
  %cmp.1.i.i = icmp sgt i8 %notsub25.i, -3
  %conv3.1.i.i = zext i1 %cmp.1.i.i to i32
  %cmp4.1.i.i = icmp sgt i32 %g.promoted.i.i, %conv3.1.i.i
  %notsub26.i = add i8 %conv1.1.i.i, -9
  %cmp.i17.i = icmp sgt i8 %notsub26.i, -3
  %conv3.i18.i = zext i1 %cmp.i17.i to i32
  %cmp4.i19.i = icmp sgt i32 %g.promoted.i.i, %conv3.i18.i
  %notsub27.i = add i8 %conv1.i.i, -9
  %cmp.1.i22.i = icmp sgt i8 %notsub27.i, -3
  %conv3.1.i23.i = zext i1 %cmp.1.i22.i to i32
  %cmp4.1.i24.i = icmp sgt i32 %xor.i.i, %conv3.1.i23.i
  %1 = and i1 %cmp4.i19.i, %cmp4.1.i24.i
  %2 = and i1 %cmp4.i.i, %1
  %3 = and i1 %cmp4.1.i.i, %2
  ret i1 %3
}
```
Output:
```
define i1 @main(i32 %g.promoted.i.i, i16 %d.promoted.i.i) {
entry:
  %0 = and i16 %d.promoted.i.i, 1
  %xor.i.i = xor i32 %g.promoted.i.i, 1
  %1 = trunc i32 %g.promoted.i.i to i8
  %2 = insertelement <2 x i8> poison, i8 %1, i32 0
  %3 = trunc i32 %xor.i.i to i8
  %4 = insertelement <2 x i8> %2, i8 %3, i32 1
  %5 = shufflevector <2 x i8> %4, <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
  %6 = add <4 x i8> %5, <i8 -9, i8 -9, i8 -1, i8 -1>
  %7 = icmp sgt <4 x i8> %6, <i8 -3, i8 -3, i8 -3, i8 -3>
  %8 = zext <4 x i1> %7 to <4 x i8>
  %9 = sext <2 x i8> %4 to <2 x i32>
  %10 = shufflevector <2 x i32> %9, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
  %11 = zext <4 x i8> %8 to <4 x i32>
  %12 = icmp sgt <4 x i32> %10, %11
  %13 = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> %12)
  ret i1 %13
}
```

cc @alexey-bataev 

Fix patch:
commit e1d22512906e69846c8f6a2d29b30832b7c12b46
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Aug 26 11:30:13 2024 -0700

    [SLP]Fix minbitwidth analysis for gather nodes with icmp users.
    
    If the node is not in MinBWs container and the user node is icmp node,
    the compiler should not check the type size of the user instruction, it
    is always 1 and is not good for actual bitwidth analysis.
    
    Fixes https://github.com/llvm/llvm-project/issues/105988

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index def73e8d0c0d..ed47ed661ab9 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -15975,6 +15975,10 @@ void BoUpSLP::computeMinimumValueSizes() {
                     auto It = MinBWs.find(TE);
                     if (It != MinBWs.end() && It->second.first > UserTESz)
                       return true;
+                    // The size of icmp is always 1 and should not be
+                    // considered.
+                    if (TE->getOpcode() == Instruction::ICmp)
+                      return true;
                     return DL->getTypeSizeInBits(U->getType()) > UserTESz;
                   }));
         })) {


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/gather-with-cmp-user.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define i1 @test(i32 %g, i16 %d) {
entry:
  %0 = and i16 %d, 1
  %xor.i.i = xor i32 %g, 1
  %conv1.i.i = trunc i32 %xor.i.i to i8
  %notsub.i = add i8 %conv1.i.i, -1
  %cmp.i.i = icmp sgt i8 %notsub.i, -3
  %conv3.i.i = zext i1 %cmp.i.i to i32
  %cmp4.i.i = icmp sgt i32 %xor.i.i, %conv3.i.i
  %conv1.1.i.i = trunc i32 %g to i8
  %notsub25.i = add i8 %conv1.1.i.i, -1
  %cmp.1.i.i = icmp sgt i8 %notsub25.i, -3
  %conv3.1.i.i = zext i1 %cmp.1.i.i to i32
  %cmp4.1.i.i = icmp sgt i32 %g, %conv3.1.i.i
  %notsub26.i = add i8 %conv1.1.i.i, -9
  %cmp.i17.i = icmp sgt i8 %notsub26.i, -3
  %conv3.i18.i = zext i1 %cmp.i17.i to i32
  %cmp4.i19.i = icmp sgt i32 %g, %conv3.i18.i
  %notsub27.i = add i8 %conv1.i.i, -9
  %cmp.1.i22.i = icmp sgt i8 %notsub27.i, -3
  %conv3.1.i23.i = zext i1 %cmp.1.i22.i to i32
  %cmp4.1.i24.i = icmp sgt i32 %xor.i.i, %conv3.1.i23.i
  %1 = and i1 %cmp4.i19.i, %cmp4.1.i24.i
  %2 = and i1 %cmp4.i.i, %1
  %3 = and i1 %cmp4.1.i.i, %2
  ret i1 %3
}