Bug type: miscompilation
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::getTreeCost
BoUpSLP::vectorizeTree
Issue title: `slp-vectorizer` miscompilation
Labels: miscompilation
llvm:SLPVectorizer
Reported by: bongjunj

Alive2 report: https://alive2.llvm.org/ce/z/FmxNvP

```llvm
----------------------------------------
define <3 x i32> @add3_i96.2(<3 x i32> %#0, <3 x i32> %#1) {
#2:
  %#3 = extractelement <3 x i32> %#0, i64 0
  %#4 = sext i32 %#3 to i64
  %#5 = extractelement <3 x i32> %#1, i64 0
  %#6 = zext i32 %#5 to i64
  %#7 = add nsw nuw i64 %#6, %#4
  %#21 = trunc i64 %#7 to i32
  %#22 = insertelement <3 x i32> %#1, i32 %#21, i32 0
  ret <3 x i32> %#22
}
=>
define <3 x i32> @add3_i96.2(<3 x i32> %#0, <3 x i32> %#1) {
#2:
  %#3 = shufflevector <3 x i32> %#1, <3 x i32> %#0, 0, 3
  %#4 = extractelement <2 x i32> %#3, i32 0
  %#5 = sext i32 %#4 to i64
  %#6 = extractelement <2 x i32> %#3, i32 1
  %#7 = sext i32 %#6 to i64
  %#8 = add nsw nuw i64 %#5, %#7
  %#22 = trunc i64 %#8 to i32
  %#23 = insertelement <3 x i32> %#1, i32 %#22, i32 0
  ret <3 x i32> %#23
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
<3 x i32> %#0 = < #x00000008 (8), #x00000000 (0), #x00000000 (0) >
<3 x i32> %#1 = < #xfffffff9 (4294967289, -7), #x00000000 (0), #x00000000 (0) >

Source:
i32 %#3 = #x00000008 (8)
i64 %#4 = #x0000000000000008 (8)
i32 %#5 = #xfffffff9 (4294967289, -7)
i64 %#6 = #x00000000fffffff9 (4294967289)
i64 %#7 = #x0000000100000001 (4294967297)
i32 %#21 = #x00000001 (1)
<3 x i32> %#22 = < #x00000001 (1), #x00000000 (0), #x00000000 (0) >

Target:
<2 x i32> %#3 = < #xfffffff9 (4294967289, -7), #x00000008 (8) >
i32 %#4 = #xfffffff9 (4294967289, -7)
i64 %#5 = #xfffffffffffffff9 (18446744073709551609, -7)
i32 %#6 = #x00000008 (8)
i64 %#7 = #x0000000000000008 (8)
i64 %#8 = poison
i32 %#22 = poison
<3 x i32> %#23 = < poison, #x00000000 (0), #x00000000 (0) >
Source value: < #x00000001 (1), #x00000000 (0), #x00000000 (0) >
Target value: < poison, #x00000000 (0), #x00000000 (0) >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```


Fix patch:
commit e914421d7fbf22059ea2180233add0c914ec80f0
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Oct 24 08:57:07 2024 -0700

    [SLP]Do correct signedness analysis for externally used scalars
    
    If the scalars is used externally is in the root node, it may have
    incorrect signedness info because of the conflict with the demanded bits
    analysis. Need to perform exact signedness analysis and compute it
    rather than rely on the precomputed value, which might be incorrect for
    alternate zext/sext nodes.
    
    Fixes #113520

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 012d85353f08..2afd02dae3a8 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -12068,8 +12068,9 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) {
     auto It = MinBWs.find(Entry);
     if (It != MinBWs.end()) {
       auto *MinTy = IntegerType::get(F->getContext(), It->second.first);
-      unsigned Extend =
-          It->second.second ? Instruction::SExt : Instruction::ZExt;
+      unsigned Extend = isKnownNonNegative(EU.Scalar, SimplifyQuery(*DL))
+                            ? Instruction::ZExt
+                            : Instruction::SExt;
       VecTy = getWidenedType(MinTy, BundleWidth);
       ExtraCost = TTI->getExtractWithExtendCost(Extend, EU.Scalar->getType(),
                                                 VecTy, EU.Lane);
@@ -15784,8 +15785,9 @@ BoUpSLP::vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
           // to the larger type.
           ExV = Ex;
           if (Scalar->getType() != Ex->getType())
-            ExV = Builder.CreateIntCast(Ex, Scalar->getType(),
-                                        MinBWs.find(E)->second.second);
+            ExV = Builder.CreateIntCast(
+                Ex, Scalar->getType(),
+                !isKnownNonNegative(Scalar, SimplifyQuery(*DL)));
           auto *I = dyn_cast<Instruction>(Ex);
           ScalarToEEs[Scalar].try_emplace(I ? I->getParent()
                                             : &F->getEntryBlock(),


Regression tests:
file: <issue>
commands: opt -S --passes=slp-vectorizer < %s
tests: test_name: add3_i96
test_body: @0 = external global i1

define <3 x i32> @add3_i96.2(<3 x i32> %0, <3 x i32> %1) {
  %4 = extractelement <3 x i32> %0, i64 0
  %5 = sext i32 %4 to i64
  %6 = extractelement <3 x i32> %1, i64 0
  %7 = zext i32 %6 to i64
  %8 = add nuw nsw i64 %7, %5
  %9 = extractelement <3 x i32> %0, i64 1
  %10 = zext i32 %9 to i64
  %11 = extractelement <3 x i32> %1, i64 1
  %12 = zext i32 %11 to i64
  %13 = add nuw nsw i64 %12, %10
  %14 = lshr i64 %8, 32
  %15 = add nuw nsw i64 %13, %14
  %16 = extractelement <3 x i32> %0, i64 2
  %17 = extractelement <3 x i32> %1, i64 2
  %18 = add i32 %17, %16
  %19 = or i64 %15, 32
  %20 = trunc i64 %19 to i32
  %21 = add i32 %18, %17
  %22 = trunc i64 %8 to i32
  %23 = insertelement <3 x i32> %1, i32 %22, i32 0
  ret <3 x i32> %23
}