Bug type: miscompilation
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::collectValuesToDemote
Issue title: [SLPVectorizer] Wrong value truncation 
Labels: miscompilation
release:backport
llvm:SLPVectorizer
Reported by: aleks-tmb

- There seems to be an issue with SLPVectorizer. In the following example, a 2-byte wide value is incorrectly truncated:

```
define i64 @test(ptr addrspace(1) %arr, i32 %a) {
entry:
  br label %loop

loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %local_1_7 = phi i64 [ 0, %entry ], [ %4, %loop ]
  %0 = sext i32 %a to i64
  %1 = add nsw i64 %0, 4294967297
  %2 = add i64 %1, %local_1_7
  %3 = and i64 %1, 1
  %4 = add i64 %2, %3
  %iv.next = add nuw nsw i64 %iv, 1
  %5 = icmp ugt i64 %iv, 355
  br i1 %5, label %exit, label %loop

exit:
  ret i64 %4
}
```
- In the loop we summarize the constant 4294967297 (`0x1'0000'0001`), but after running SLPVectorizer over the unrolled loop, the constant is truncated to `1`:
```
loop: 
  %iv = phi i64 [ 0, %entry ], [ %iv.next.16, %loop ]
  %local_1_7 = phi i64 [ 0, %entry ], [ %op.rdx3, %loop ]
  %2 = add <16 x i32> %1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
  %3 = sext <16 x i32> %2 to <16 x i64>
...
```
- Command to reproduce: `opt -passes=loop-unroll,slp-vectorizer -unroll-count=17`
- https://godbolt.org/z/zcPefTPzW
- Looks like the issue was caused by the  https://github.com/llvm/llvm-project/commit/7f2167868d8c1cedd3915883412b9c787a2f01db

@alexey-bataev Could you please take a look?


Comments: author: nikic
body: This probably needs an LLVM 19 backport?

/cherry-pick 65ac12d3c9877ecf5b97552364e7eead887d94eb 56140a8258a3498cfcd9f0f05c182457d43cbfd2

Fix patch:
commit 56140a8258a3498cfcd9f0f05c182457d43cbfd2
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Aug 15 07:57:37 2024 -0700

    [SLP]Fix PR104422: Wrong value truncation
    
    The minbitwidth restrictions can be skipped only for immediate reduced
    values, for other nodes still need to check if external users allow
    bitwidth reduction.
    
    Fixes https://github.com/llvm/llvm-project/issues/104422

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 81841a8f6928..87b4ed599b5b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -15663,7 +15663,8 @@ bool BoUpSLP::collectValuesToDemote(
   if (any_of(E.Scalars, [&](Value *V) {
         return !all_of(V->users(), [=](User *U) {
           return getTreeEntry(U) ||
-                 (UserIgnoreList && UserIgnoreList->contains(U)) ||
+                 (E.Idx == 0 && UserIgnoreList &&
+                  UserIgnoreList->contains(U)) ||
                  (!isa<CmpInst>(U) && U->getType()->isSized() &&
                   !U->getType()->isScalableTy() &&
                   DL->getTypeSizeInBits(U->getType()) <= BitWidth);


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/operand-is-reduced-val.ll
commands: opt -S --passes=slp-vectorizer < %s -slp-threshold=-10
tests: test_name: src
test_body: define i64 @src(i32 %a) {
entry:
  %0 = sext i32 %a to i64
  %1 = add nsw i64 %0, 4294967297
  %2 = sext i32 %a to i64
  %3 = add nsw i64 %2, 4294967297
  %4 = add i64 %3, %1
  %5 = and i64 %3, 1
  %6 = add i64 %4, %5
  %7 = sext i32 %a to i64
  %8 = add nsw i64 %7, 4294967297
  %9 = add i64 %8, %6
  %10 = and i64 %8, 1
  %11 = add i64 %9, %10
  %12 = sext i32 %a to i64
  %13 = add nsw i64 %12, 4294967297
  %14 = add i64 %13, %11
  %15 = and i64 %13, 1
  %16 = add i64 %14, %15
  %17 = sext i32 %a to i64
  %18 = add nsw i64 %17, 4294967297
  %19 = add i64 %18, %16
  %20 = and i64 %18, 1
  %21 = add i64 %19, %20
  ret i64 %21
}