Bug type: miscompilation
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp: canonicalizeSaturatedAdd
Issue title: Poison value wrongly propagates through vector operations on an optimized code
Labels: miscompilation
llvm:instcombine
Reported by: bongjunj

https://github.com/llvm/llvm-project/blob/5d4a0d54b5269bad1410e6db957836fe98634069/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp#L1050-L1060

Alive2 report: https://alive2.llvm.org/ce/z/6tSdhb

```llvm
----------------------------------------
define <2 x i32> @uadd_sat_not_ugt_commute_add.2(<2 x i32> %x, <2 x i32> %yp) {
#0:
  %#1 = sdiv <2 x i32> { 2442, 4242 }, %yp
  %notx = xor <2 x i32> %x, { 4294967295, poison }
  %a = add nuw <2 x i32> %#1, %notx
  %c = icmp ugt <2 x i32> %#1, %x
  %r = select <2 x i1> %c, <2 x i32> { 4294967295, 4294967295 }, <2 x i32> %a
  ret <2 x i32> %r
}
=>
define <2 x i32> @uadd_sat_not_ugt_commute_add.2(<2 x i32> %x, <2 x i32> %yp) {
#0:
  %#1 = sdiv <2 x i32> { 2442, 4242 }, %yp
  %notx = xor <2 x i32> %x, { 4294967295, poison }
  %r = uadd_sat <2 x i32> %#1, %notx
  ret <2 x i32> %r
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
<2 x i32> %x = < poison, #x00000000 (0) >
<2 x i32> %yp = < #x00000008 (8), #x0000000e (14) >

Source:
<2 x i32> %#1 = < #x00000131 (305), #x0000012f (303) >
<2 x i32> %notx = < poison, poison >
<2 x i32> %a = < poison, poison >
<2 x i1> %c = < poison, #x1 (1) >
<2 x i32> %r = < poison, #xffffffff (4294967295, -1) >

Target:
<2 x i32> %#1 = < #x00000131 (305), #x0000012f (303) >
<2 x i32> %notx = < poison, poison >
<2 x i32> %r = < poison, poison >
Source value: < poison, #xffffffff (4294967295, -1) >
Target value: < poison, poison >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```


Fix patch:
commit e577f14b670ee2ae6bb717133310b215be4331b3
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Nov 1 22:18:44 2024 +0800

    [InstCombine] Use `m_NotForbidPoison` when folding `(X u< Y) ? -1 : (~X + Y) --> uadd.sat(~X, Y)` (#114345)
    
    Alive2: https://alive2.llvm.org/ce/z/mTGCo-
    We cannot reuse `~X` if `m_AllOnes` matches a vector constant with some
    poison elts. An alternative solution is to create a new not instead of
    reusing `~X`. But it doesn't worth the effort because we need to add a
    one-use check.
    
    Fixes https://github.com/llvm/llvm-project/issues/113869.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 162ebebf1b8f..999ad1adff20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1056,7 +1056,7 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
   // Strictness of the comparison is irrelevant.
   X = Cmp0;
   Y = Cmp1;
-  if (match(FVal, m_c_Add(m_Not(m_Specific(X)), m_Specific(Y)))) {
+  if (match(FVal, m_c_Add(m_NotForbidPoison(m_Specific(X)), m_Specific(Y)))) {
     // (X u< Y) ? -1 : (~X + Y) --> uadd.sat(~X, Y)
     // (X u< Y) ? -1 : (Y + ~X) --> uadd.sat(Y, ~X)
     BinaryOperator *BO = cast<BinaryOperator>(FVal);


Regression tests:
file: llvm/test/Transforms/InstCombine/saturating-add-sub.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: uadd_sat_not_commute_select
test_body: define i32 @uadd_sat_not_commute_select(i32 %x, i32 %y) {
  %notx = xor i32 %x, -1
  %a = add i32 %notx, %y
  %c = icmp ult i32 %y, %x
  %r = select i1 %c, i32 %a, i32 -1
  ret i32 %r
}

test_name: uadd_sat_not_ugt_commute_add
test_body: define <2 x i32> @uadd_sat_not_ugt_commute_add(<2 x i32> %x, <2 x i32> %yp) {
  %y = sdiv <2 x i32> %yp, <i32 2442, i32 4242>
  %notx = xor <2 x i32> %x, splat (i32 -1)
  %a = add <2 x i32> %y, %notx
  %c = icmp ugt <2 x i32> %y, %x
  %r = select <2 x i1> %c, <2 x i32> splat (i32 -1), <2 x i32> %a
  ret <2 x i32> %r
}

test_name: uadd_sat_not_ugt_commute_add_partial_poison
test_body: define <2 x i32> @uadd_sat_not_ugt_commute_add_partial_poison(<2 x i32> %x, <2 x i32> %yp) {
  %notx = xor <2 x i32> %x, <i32 -1, i32 poison>
  %a = add nuw <2 x i32> %yp, %notx
  %c = icmp ugt <2 x i32> %yp, %x
  %r = select <2 x i1> %c, <2 x i32> splat (i32 -1), <2 x i32> %a
  ret <2 x i32> %r
}