Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/VPlan.cpp: VPTransformState::get
Issue title: LoopVectorizer asserts:  Assertion `(VF.isScalar() || Def->isLiveIn() || (hasScalarValue(Def, VPIteration(Part, 0)) && Data.PerPartScalars[Def][Part].size() == 1)) && "Trying to access a single scalar per part but has multiple scalars " "per part.
Labels: vectorizers
crash
Reported by: JonPsson1

[tc_crash35_aftercreduce.ll.tar.gz](https://github.com/llvm/llvm-project/files/14988465/tc_crash35_aftercreduce.ll.tar.gz)

opt -mtriple=s390x-unknown-linux -mcpu=z16 -O3 tc_crash35_aftercreduce.ll -o /dev/null

VPlan.cpp:253: llvm::Value* llvm::VPTransformState::get(llvm::VPValue*, unsigned int, bool): Assertion `(VF.isScalar() || Def->isLiveIn() || (hasScalarValue(Def, VPIteration(Part, 0)) && Data.PerPartScalars[Def][Part].size() == 1)) && "Trying to access a single scalar per part but has multiple scalars " "per part."' failed.

@fhahn 

Comments: author: fhahn
body: Should be fixed now, sorry for the delay @JonPsson1 !

Fix patch:
commit b8741cc185e89a95c9161218084f7c8b5578cf96
Author: Florian Hahn <flo@fhahn.com>
Date:   Fri Jul 19 10:33:07 2024 +0100

    [VPlan] Relax assertion retrieving a scalar from VPTransformState::get.
    
    The current assertion VPTransformState::get when retrieving a single
    scalar only does not account for cases where a def has multiple users,
    some demanding all scalar lanes, some demanding only a single scalar.
    
    For an example, see the modified test case. Relax the assertion by also
    allowing requesting scalar lanes only when the Def doesn't have only its
    first lane used.
    
    Fixes https://github.com/llvm/llvm-project/issues/88849.

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 83a035fb4df8..58de6256900f 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -254,6 +254,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() || hasVectorValue(Def, Part) ||
+            !vputils::onlyFirstLaneUsed(Def) ||
             (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/SystemZ/scalar-steps-with-users-demanding-all-lanes-and-first-lane-only.ll
commands: opt -p loop-vectorize -mtriple=s390x-unknown-linux -mcpu=z16 -S %s
tests: test_name: test_scalar_iv_steps_used_by_replicate_and_first_lane_only_vpinst
test_body: target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"

@src = external global [8 x i32], align 4

define void @test_scalar_iv_steps_used_by_replicate_and_first_lane_only_vpinst(ptr noalias %dst, ptr noalias %src.1) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %mul.iv = mul nsw i64 %iv, 4
  %gep.src.1 = getelementptr inbounds i8, ptr %src.1, i64 %mul.iv
  %l.1 = load i8, ptr %gep.src.1, align 1
  %c = icmp eq i8 %l.1, 0
  br i1 %c, label %then, label %loop.latch

then:                                             ; preds = %loop.header
  %iv.or = or disjoint i64 %iv, 4
  %gep.src = getelementptr inbounds [8 x i32], ptr @src, i64 0, i64 %iv.or
  %l.2 = load i32, ptr %gep.src, align 4
  store i32 %l.2, ptr %dst, align 4
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %iv.next = add nuw nsw i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 4
  br i1 %ec, label %exit, label %loop.header

exit:                                             ; preds = %loop.latch
  ret void
}