Bug type: miscompilation
Component: VectorCombine
Bug location: llvm/lib/Transforms/Vectorize/VectorCombine.cpp: VectorCombine::scalarizeBinopOrCmp
Issue title: [VectorCombine] UB triggered after optimization
Labels: miscompilation
vectorizers
Reported by: bongjunj

https://github.com/llvm/llvm-project/blob/c93e001ca695e905cb965b36d63f7a348d1dd809/llvm/lib/Transforms/Vectorize/VectorCombine.cpp#L1013-L1031

Alive2 report: https://alive2.llvm.org/ce/z/78CM4x

```llvm
----------------------------------------
define <2 x i8> @sdiv_constant_op1_not_undef_lane.2(i8 %x) {
#0:
  %ins = insertelement <2 x i8> poison, i8 %x, i32 3
  %bo = sdiv <2 x i8> %ins, { 5, 2 }
  ret <2 x i8> %bo
}
=>
define <2 x i8> @sdiv_constant_op1_not_undef_lane.2(i8 %x) {
#0:
  %bo.scalar = sdiv i8 %x, poison
  %bo = insertelement <2 x i8> poison, i8 %bo.scalar, i64 3
  ret <2 x i8> %bo
}
Transformation doesn't verify!

ERROR: Source is more defined than target

Example:
i8 %x = poison

Source:
<2 x i8> %ins = < poison, poison >
<2 x i8> %bo = < poison, poison >

Target:
i8 %bo.scalar = UB triggered!



----------------------------------------
define <2 x i64> @urem_constant_op1_not_undef_lane.2(i64 %x) {
#0:
  %ins = insertelement <2 x i64> poison, i64 %x, i32 4294967295
  %bo = urem <2 x i64> %ins, { 5, 2 }
  ret <2 x i64> %bo
}
=>
define <2 x i64> @urem_constant_op1_not_undef_lane.2(i64 %x) {
#0:
  %bo.scalar = urem i64 %x, poison
  %bo = insertelement <2 x i64> poison, i64 %bo.scalar, i64 4294967295
  ret <2 x i64> %bo
}
Transformation doesn't verify!

ERROR: Source is more defined than target

Example:
i64 %x = poison

Source:
<2 x i64> %ins = < poison, poison >
<2 x i64> %bo = < poison, poison >

Target:
i64 %bo.scalar = UB triggered!


Summary:
  0 correct transformations
  2 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```


Fix patch:
commit 958e37cd1feabf29fb1cc3fb5ac82051ad8d43eb
Author: Simon Pilgrim <llvm-dev@redking.me.uk>
Date:   Sat Nov 9 15:59:52 2024 +0000

    [VectorCombine] scalarizeBinopOrCmp - check for out of bounds element indices
    
    Fixes #115575

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 04ea12ef0f12..b8754b03c2eb 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -952,6 +952,12 @@ bool VectorCombine::scalarizeBinopOrCmp(Instruction &I) {
   if (!IsConst0 && !IsConst1 && Index0 != Index1)
     return false;
 
+  auto *VecTy0 = cast<VectorType>(Ins0->getType());
+  auto *VecTy1 = cast<VectorType>(Ins1->getType());
+  if (VecTy0->getElementCount().getKnownMinValue() <= Index0 ||
+      VecTy1->getElementCount().getKnownMinValue() <= Index1)
+    return false;
+
   // Bail for single insertion if it is a load.
   // TODO: Handle this once getVectorInstrCost can cost for load/stores.
   auto *I0 = dyn_cast_or_null<Instruction>(V0);


Regression tests:
file: llvm/test/Transforms/VectorCombine/X86/pr115575.ll
commands: opt < %s -passes=vector-combine -S -mtriple=x86_64--
tests: test_name: PR115575
test_body: define <2 x i8> @PR115575(i8 %x) {
  %ins = insertelement <2 x i8> poison, i8 %x, i32 3
  %bo = sdiv <2 x i8> %ins, <i8 5, i8 2>
  ret <2 x i8> %bo
}