Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/VPlan.cpp: VPTransformState::get
Issue title: New LLVM vectorizer crash in assertion
Labels: vectorizers
crash
Reported by: cheshire

@fhahn hits an assertion introduced in https://github.com/llvm/llvm-project/pull/80271

Input file: https://gist.github.com/cheshire/e504c63db9bdb300fbdcc1df2e183bd8

Repro:

```
opt -S -passes=loop-vectorize -mattr=+prfchw,-cldemote,+avx,+aes,+sahf,+pclmul,-xop,+crc32,+xsaves,-avx512fp16,-usermsr,-sm4,-egpr,+sse4.1,-avx512ifma,+xsave,+sse4.2,-avx512pf,-tsxldtrk,-ptwrite,-widekl,-sm3,+invpcid,+64bit,+xsavec,-avx10.1-512,-avx512vpopcntdq,+cmov,-avx512vp2intersect,+avx512cd,+movbe,-avxvnniint8,-avx512er,-ccmp,-amx-int8,-kl,-avx10.1-256,+evex512,-avxvnni,+rtm,+adx,+avx2,-hreset,-movdiri,-serialize,-sha512,-vpclmulqdq,+avx512vl,-uintr,-cf,+clflushopt,-raoint,-cmpccxadd,+bmi,-amx-tile,+sse,-gfni,-avxvnniint16,-amx-fp16,-ndd,+xsaveopt,+rdrnd,+avx512f,-amx-bf16,-avx512bf16,-avx512vnni,-push2pop2,+cx8,+avx512bw,+sse3,+pku,+fsgsbase,-clzero,-mwaitx,-lwp,+lzcnt,-sha,-movdir64b,-ppx,-wbnoinvd,-enqcmd,-prefetchwt1,-avxneconvert,-tbm,-pconfig,-amx-complex,+ssse3,+cx16,+bmi2,+fma,+popcnt,-avxifma,+f16c,-avx512bitalg,-rdpru,+clwb,+mmx,+sse2,+rdseed,-avx512vbmi2,-prefetchi,-rdpid,-fma4,-avx512vbmi,-shstk,-vaes,-waitpkg,-sgx,+fxsr,+avx512dq,-sse4a -mcpu=skylake-avx512 /tmp/minimized_crash.ll
```


Fix patch:
commit 67d840b60fbd75ca1b52d77bd3353771ec853735
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue May 14 19:10:48 2024 +0100

    [VPlan] Relax over-aggressive assertion in VPTransformState::get().
    
    There are cases where a vector value has some users that demand the
    the single scalar value only (NeedsScalar), while other users demand the
    vector value (see attached test cases). In those cases, the NeedsScalar
    users should only demand the first lane.
    
    Fixes https://github.com/llvm/llvm-project/issues/91883.

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 999236ae8489..27f8e239b1c0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -246,7 +246,7 @@ Value *VPTransformState::get(VPValue *Def, const VPIteration &Instance) {
 
 Value *VPTransformState::get(VPValue *Def, unsigned Part, bool NeedsScalar) {
   if (NeedsScalar) {
-    assert((VF.isScalar() || Def->isLiveIn() ||
+    assert((VF.isScalar() || Def->isLiveIn() || hasVectorValue(Def, Part) ||
             (hasScalarValue(Def, VPIteration(Part, 0)) &&
              Data.PerPartScalars[Def][Part].size() == 1)) &&
            "Trying to access a single scalar per part but has multiple scalars "


Regression tests:
file: llvm/test/Transforms/LoopVectorize/X86/widened-value-used-as-scalar-and-first-lane.ll
commands: opt -S -passes=loop-vectorize -mcpu=skylake-avx512 -mtriple=x86_64-apple-macosx -S %s
tests: test_name: <module>
test_body: 
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

; Test cases based on https://github.com/llvm/llvm-project/issues/91883.
define void @iv.4_used_as_vector_and_first_lane(ptr %src, ptr noalias %dst) {
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %g.src = getelementptr inbounds i64, ptr %src, i64 %iv
  %l = load i64, ptr %g.src
  %iv.4 = add nuw nsw i64 %iv, 4
  %c = icmp ule i64 %l, 128
  br i1 %c, label %loop.then, label %loop.latch

loop.then:
  %or = or disjoint i64 %iv.4, 1
  %g.dst = getelementptr inbounds i64, ptr %dst, i64 %or
  store i64 %iv.4, ptr %g.dst, align 4
  br label %loop.latch

loop.latch:
  %iv.next = add nuw nsw i64 %iv, 1
  %exitcond = icmp eq i64 %iv.next, 32
  br i1 %exitcond, label %exit, label %loop.header

exit:
  ret void
}

define void @iv.4_used_as_first_lane(ptr %src, ptr noalias %dst) {
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %g.src = getelementptr inbounds i64, ptr %src, i64 %iv
  %l = load i64, ptr %g.src
  %iv.4 = add nuw nsw i64 %iv, 4
  %c = icmp ule i64 %l, 128
  br i1 %c, label %loop.then, label %loop.latch

loop.then:
  %or = or disjoint i64 %iv.4, 1
  %g.dst = getelementptr inbounds i64, ptr %dst, i64 %or
  store i64 %l, ptr %g.dst, align 4
  br label %loop.latch

loop.latch:
  %iv.next = add nuw nsw i64 %iv, 1
  %exitcond = icmp eq i64 %iv.next, 32
  br i1 %exitcond, label %exit, label %loop.header

exit:
  ret void
}
;.
;.