Bug type: miscompilation
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp: InstCombinerImpl::visitSelectInst
Issue title: integer vector miscompile from instcombine
Labels: miscompilation
llvm:instcombine
Reported by: regehr

I believe this is being mis-optimized:
```lllvm
define <4 x i32> @f(<4 x i32> %0) {
  %2 = icmp eq <4 x i32> %0, zeroinitializer
  %3 = shufflevector <4 x i32> %0, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 1, i32 0, i32 3>
  %4 = select <4 x i1> %2, <4 x i32> %3, <4 x i32> zeroinitializer
  ret <4 x i32> %4
}
```
I'll just give Alive's reasoning, which is pretty easy to follow and seems correct:
```
regehr@ohm:~$ ~/alive2-regehr/build/alive-tv -passes=instcombine foo.ll

----------------------------------------
define <4 x i32> @f(<4 x i32> %#0) {
#1:
  %#2 = icmp eq <4 x i32> %#0, { 0, 0, 0, 0 }
  %#3 = shufflevector <4 x i32> %#0, <4 x i32> { 0, 0, 0, 0 }, 1, 1, 0, 3
  %#4 = select <4 x i1> %#2, <4 x i32> %#3, <4 x i32> { 0, 0, 0, 0 }
  ret <4 x i32> %#4
}
=>
define <4 x i32> @f(<4 x i32> %#0) {
#1:
  ret <4 x i32> { 0, 0, 0, 0 }
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:
<4 x i32> %#0 = < #x00000000 (0), #x00000001 (1), #x00000000 (0), poison >

Source:
<4 x i1> %#2 = < #x1 (1), #x0 (0), #x1 (1), poison >
<4 x i32> %#3 = < #x00000001 (1), #x00000001 (1), #x00000000 (0), poison >
<4 x i32> %#4 = < #x00000001 (1), #x00000000 (0), #x00000000 (0), poison >

Target:
Source value: < #x00000001 (1), #x00000000 (0), #x00000000 (0), poison >
Target value: < #x00000000 (0), #x00000000 (0), #x00000000 (0), #x00000000 (0) >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
regehr@ohm:~$ 
```
cc @nunoplopes 

Comments: author: nikic
body: Probably caused by https://github.com/llvm/llvm-project/commit/77eb05683082dd3751ccfab963f5160f1852058d. Fell into the vector select trap again.

Fix patch:
commit 3969d2c3b5f42e4a180f5205efa780b0f950d733
Author: Nikita Popov <npopov@redhat.com>
Date:   Wed Jul 3 09:47:01 2024 +0200

    [InstCombine] Disable select known bits fold for vectors
    
    This is not safe if the simplification ends up looking through
    lane-crossing operations. For now, we don't have a good way to
    limit this in computeKnownBits(), so just disable vector handling
    entirely.
    
    Fixes https://github.com/llvm/llvm-project/issues/97475.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 736013395e8c..394dfca262e1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -4049,7 +4049,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
   if (CondVal->getType() == SI.getType() && isKnownInversion(FalseVal, TrueVal))
     return BinaryOperator::CreateXor(CondVal, FalseVal);
 
-  if (SelType->isIntOrIntVectorTy() &&
+  // For vectors, this transform is only safe if the simplification does not
+  // look through any lane-crossing operations. For now, limit to scalars only.
+  if (SelType->isIntegerTy() &&
       (!isa<Constant>(TrueVal) || !isa<Constant>(FalseVal))) {
     // Try to simplify select arms based on KnownBits implied by the condition.
     CondContext CC(CondVal);


Regression tests:
file: llvm/test/Transforms/InstCombine/select-binop-cmp.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: select_xor_icmp_vec_bad
test_body: define <2 x i8> @select_xor_icmp_vec_bad(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
  %A = icmp eq <2 x i8> %x, <i8 5, i8 3>
  %B = xor <2 x i8> %x, %z
  %C = select <2 x i1> %A, <2 x i8> %B, <2 x i8> %y
  ret <2 x i8> %C
}

test_name: vec_select_no_equivalence
test_body: define <2 x i32> @vec_select_no_equivalence(<2 x i32> %x) {
  %x10 = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> <i32 1, i32 0>
  %cond = icmp eq <2 x i32> %x, zeroinitializer
  %s = select <2 x i1> %cond, <2 x i32> %x10, <2 x i32> %x
  ret <2 x i32> %s
}