Bug type: miscompilation
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp: InstCombinerImpl::SimplifyDemandedVectorElts
Issue title: Wrong select folding for undef conditions by InstCombine
Labels: miscompilation
llvm:instcombine
Reported by: bongjunj

https://github.com/llvm/llvm-project/blob/7eae9bb856135136cddc4208a2b1546e9db44c9c/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp#L3582-L3585

Alive2 report: https://alive2.llvm.org/ce/z/Qtu72J


```ll
----------------------------------------
define <2 x i1> @fun0(<2 x i1> %val0, <2 x i1> %val1) {
#0:
  %val2 = select <2 x i1> %val0, <2 x i1> %val0, <2 x i1> %val0
  %val3 = select <2 x i1> { undef, 1 }, <2 x i1> { 1, 1 }, <2 x i1> %val2
  ret <2 x i1> %val3
}
=>
define <2 x i1> @fun0(<2 x i1> %val0, <2 x i1> %val1) {
#0:
  ret <2 x i1> { poison, 1 }
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
<2 x i1> %val0 = < #x0 (0), #x0 (0) >
<2 x i1> %val1 = < #x0 (0), #x0 (0) >

Source:
<2 x i1> %val2 = < #x0 (0), #x0 (0) >
<2 x i1> %val3 = < #x0 (0)	[based on undef value], #x1 (1) >

Target:
Source value: < #x0 (0), #x1 (1) >
Target value: < poison, #x1 (1) >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```

Comments: author: jf-botto
body: Would this issue be to fix InstCombine to not try to optimise it or get InstCombine to pick  `<2 x i1> { 1, 1 }` because `undef` let's it pick either values and picking a constant vector is better than picking a variable?
author: nikic
body: The problematic step seems to be this one: https://alive2.llvm.org/ce/z/C2waWU

I don't think the quoted code is responsible for this, as it is guarded by `!isa<Constant>(CondVal)`.
author: jf-botto
body: I think the problem is with how `SimplifyDemandedVectorElts` handles the undef: https://github.com/llvm/llvm-project/blob/af80d3a248101d6f5d9d5e229c7899136b8ce0b8/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp#L1721-L1760
author: nikic
body: @jf-botto Agree. It assumes that !isNullValue() means "is true", which is not the case.

Fix patch:
commit 9304af3927caecdb43d3a9b5d16c6a5b7a6b5594
Author: Jorge Botto <23462171+jf-botto@users.noreply.github.com>
Date:   Fri Aug 9 11:52:56 2024 +0100

    [InstCombine] Fixing wrong select folding in vectors with undef elements (#102244)
    
    This PR fixes https://github.com/llvm/llvm-project/issues/98435.
    `SimplifyDemandedVectorElts` mishandles the undef by assuming that
    !isNullValue() means the condition is true.
    
    By preventing any value that we're not certain equals 1 or 0, it avoids
    having to make any particular choice by not demanding bits from a
    particular branch with potentially picking a wrong value.
    
    Proof: https://alive2.llvm.org/ce/z/r8CmEu

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index c494fec84c1e..153d8c238ed4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1735,17 +1735,12 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
     APInt DemandedLHS(DemandedElts), DemandedRHS(DemandedElts);
     if (auto *CV = dyn_cast<ConstantVector>(Sel->getCondition())) {
       for (unsigned i = 0; i < VWidth; i++) {
-        // isNullValue() always returns false when called on a ConstantExpr.
-        // Skip constant expressions to avoid propagating incorrect information.
         Constant *CElt = CV->getAggregateElement(i);
-        if (isa<ConstantExpr>(CElt))
-          continue;
-        // TODO: If a select condition element is undef, we can demand from
-        // either side. If one side is known undef, choosing that side would
-        // propagate undef.
+
+        // isNullValue() always returns false when called on a ConstantExpr.
         if (CElt->isNullValue())
           DemandedLHS.clearBit(i);
-        else
+        else if (CElt->isOneValue())
           DemandedRHS.clearBit(i);
       }
     }


Regression tests:
file: llvm/test/Transforms/InstCombine/pr98435.ll
commands: opt -S -passes=instcombine < %s 2>&1
tests: test_name: pr98435
test_body: define <2 x i1> @pr98435(<2 x i1> %val) {
  %val1 = select <2 x i1> <i1 undef, i1 true>, <2 x i1> splat (i1 true), <2 x i1> %val
  ret <2 x i1> %val1
}