Bug type: miscompilation
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp: foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed
Issue title: [InstCombine] `samesign` should be dropped when folding logical and of icmps
Labels: miscompilation
llvm:instcombine
Reported by: dtcxzyw

Reproducer: https://alive2.llvm.org/ce/z/YSW_NC
```
define i1 @src(i8 %0, i8 %1) {
start:
  %2 = icmp samesign eq i8 %0, -1
  %3 = icmp ne i8 %0, 0
  %4 = icmp ugt i8 %0, %0
  %result = select i1 %3, i1 %2, i1 %4
  ret i1 %result
}

define i1 @tgt(i8 %0, i8 %1) {
start:
  %2 = icmp samesign eq i8 %0, -1
  ret i1 %2
}
```
```

----------------------------------------
define i1 @src(i8 %#0, i8 %#1) {
start:
  %#2 = icmp samesign eq i8 %#0, 255
  %#3 = icmp ne i8 %#0, 0
  %#4 = icmp ugt i8 %#0, %#0
  %result = select i1 %#3, i1 %#2, i1 %#4
  ret i1 %result
}
=>
define i1 @tgt(i8 %#0, i8 %#1) {
start:
  %#2 = icmp samesign eq i8 %#0, 255
  ret i1 %#2
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i8 %#0 = #x00 (0)
i8 %#1 = poison

Source:
i1 %#2 = poison
i1 %#3 = #x0 (0)
i1 %#4 = #x0 (0)
i1 %result = #x0 (0)

Target:
i1 %#2 = poison
Source value: #x0 (0)
Target value: poison
```
Reported by https://github.com/dtcxzyw/llvm-mutation-based-fuzz-service/issues/14 while reviewing https://github.com/llvm/llvm-project/pull/120177.





Fix patch:
commit 6f68010f9123aae9f6f105d7a11af22458518ad7
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Wed Dec 18 20:40:33 2024 +0800

    [InstCombine] Drop samesign flags in `foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed` (#120373)
    
    Counterexamples: https://alive2.llvm.org/ce/z/6Ks8Qz
    Closes https://github.com/llvm/llvm-project/issues/120361.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index dff9304be64d..e576eea4ca36 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -455,14 +455,20 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
   // RHS. For example,
   // (icmp ne (A & 255), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
   // (icmp ne (A & 15), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
-  if (IsSuperSetOrEqual(BCst, DCst))
+  if (IsSuperSetOrEqual(BCst, DCst)) {
+    // We can't guarantee that samesign hold after this fold.
+    RHS->setSameSign(false);
     return RHS;
+  }
   // Otherwise, B is a subset of D. If B and E have a common bit set,
   // ie. (B & E) != 0, then LHS is subsumed by RHS. For example.
   // (icmp ne (A & 12), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
   assert(IsSubSetOrEqual(BCst, DCst) && "Precondition due to above code");
-  if ((*BCst & ECst) != 0)
+  if ((*BCst & ECst) != 0) {
+    // We can't guarantee that samesign hold after this fold.
+    RHS->setSameSign(false);
     return RHS;
+  }
   // Otherwise, LHS and RHS contradict and the whole expression becomes false
   // (or true if negated.) For example,
   // (icmp ne (A & 7), 0) & (icmp eq (A & 15), 8) -> false.


Regression tests:
file: llvm/test/Transforms/InstCombine/icmp-logical.ll
commands: opt -passes=instcombine -S -o - %s
tests: test_name: pr120361
test_body: define i1 @pr120361(i8 %x, i8 %y) {
  %cmp1 = icmp samesign eq i8 %x, -1
  %cmp2 = icmp ne i8 %x, 0
  %result = select i1 %cmp2, i1 %cmp1, i1 false
  ret i1 %result
}

test_name: pr120361_v2
test_body: define i1 @pr120361_v2(i32 %x) {
  %and1 = and i32 %x, 15
  %cmp1 = icmp ne i32 %and1, 0
  %and2 = and i32 %x, -113
  %cmp2 = icmp samesign eq i32 %and2, 15
  %and = select i1 %cmp1, i1 %cmp2, i1 false
  ret i1 %and
}

test_name: masked_icmps_bmask_notmixed_not_subset_notoptimized
test_body: define i1 @masked_icmps_bmask_notmixed_not_subset_notoptimized(i32 %A) {
  %mask1 = and i32 %A, 254
  %tst1 = icmp ne i32 %mask1, 252
  %mask2 = and i32 %A, 253
  %tst2 = icmp ne i32 %mask2, 252
  %res = and i1 %tst1, %tst2
  ret i1 %res
}