Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/VPlan.cpp: VPTransformState::get
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp: VPInstruction::generatePerPart
Issue title: Assertion `hasVectorValue(Def, Instance.Part)' failed.
Labels: vectorizers
crash-on-valid
Reported by: TatyanaDoubts

To reproduce run the following test opt with -passes loop-vectorize:
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
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-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define i32 @wombat() gc "statepoint-example" {
bb:
  br label %bb2

bb1:                                              ; preds = %bb2
  ret i32 0

bb2:                                              ; preds = %bb2, %bb
  %phi = phi i64 [ 0, %bb ], [ %add, %bb2 ]
  %phi3 = phi i32 [ 0, %bb ], [ %load, %bb2 ]
  %add = add i64 %phi, 1
  %load = load i32, ptr addrspace(1) null, align 4
  %icmp = icmp ult i64 %phi, 1
  br i1 %icmp, label %bb2, label %bb1
}
```
Reproducer: https://godbolt.org/z/cv7Tf3vba

Stack dump:
```
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes loop-vectorize <source>
 #0 0x0000000004e41688 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e41688)
 #1 0x0000000004e3eddc SignalHandler(int) Signals.cpp:0:0
 #2 0x00007ec2abe42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007ec2abe969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007ec2abe42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007ec2abe287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00007ec2abe2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x00007ec2abe39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000003fecdce (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3fecdce)
 #9 0x0000000004008abe llvm::VPInstruction::generatePerPart(llvm::VPTransformState&, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4008abe)
#10 0x000000000400ae5e llvm::VPInstruction::execute(llvm::VPTransformState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x400ae5e)
#11 0x0000000003fe5fbf llvm::VPBasicBlock::executeRecipes(llvm::VPTransformState*, llvm::BasicBlock*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3fe5fbf)
#12 0x0000000003fe9cb0 llvm::VPBasicBlock::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3fe9cb0)
#13 0x0000000003feda3e llvm::VPlan::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3feda3e)
#14 0x0000000003eda4e5 llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, bool, llvm::DenseMap<llvm::SCEV const*, llvm::Value*, llvm::DenseMapInfo<llvm::SCEV const*, void>, llvm::detail::DenseMapPair<llvm::SCEV const*, llvm::Value*>> const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3eda4e5)
#15 0x0000000003eef18b llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3eef18b)
#16 0x0000000003ef1a4d llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3ef1a4d)
#17 0x0000000003ef2c5b llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3ef2c5b)
#18 0x0000000002e0679e llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2e0679e)
#19 0x0000000004c49a6c llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c49a6c)
#20 0x0000000000dbabee llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xdbabee)
#21 0x0000000004c483ae llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c483ae)
#22 0x0000000000dbc65e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xdbc65e)
#23 0x0000000004c462bc llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c462bc)
#24 0x00000000008db912 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8db912)
#25 0x00000000008ceabc optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ceabc)
#26 0x00007ec2abe29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#27 0x00007ec2abe29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#28 0x00000000008c5f0e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8c5f0e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```



Comments: author: dtcxzyw
body: cc @fhahn 

Fix patch:
commit 40a72f8cc414726a8be234a260650fd62354da21
Author: Florian Hahn <flo@fhahn.com>
Date:   Fri Jun 14 22:16:51 2024 +0100

    [VPlan] Support extracting any lane of uniform value.
    
    If the value we are extracting a lane from is uniform, only the first
    lane will be set. Return lane 0 for any requested lane.
    
    This fixes a crash when trying to extract the last lane for a
    first-order recurrence resume value.
    
    Fixes https://github.com/llvm/llvm-project/issues/95520.

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index f17be451e684..348a2be5072b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -231,6 +231,11 @@ Value *VPTransformState::get(VPValue *Def, const VPIteration &Instance) {
     return Data
         .PerPartScalars[Def][Instance.Part][Instance.Lane.mapToCacheIndex(VF)];
   }
+  if (!Instance.Lane.isFirstLane() &&
+      vputils::isUniformAfterVectorization(Def) &&
+      hasScalarValue(Def, {Instance.Part, VPLane::getFirstLane()})) {
+    return Data.PerPartScalars[Def][Instance.Part][0];
+  }
 
   assert(hasVectorValue(Def, Instance.Part));
   auto *VecPart = Data.PerPartOutput[Def][Instance.Part];
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 7a482455473e..a3ff6395bb39 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -577,7 +577,8 @@ Value *VPInstruction::generatePerPart(VPTransformState &State, unsigned Part) {
       // When loop is unrolled without vectorizing, retrieve UF - Offset.
       Res = State.get(getOperand(0), State.UF - Offset);
     }
-    Res->setName(Name);
+    if (isa<ExtractElementInst>(Res))
+      Res->setName(Name);
     return Res;
   }
   case VPInstruction::LogicalAnd: {


Regression tests:
file: llvm/test/Transforms/LoopVectorize/AArch64/reduction-recurrence-costs-sve.ll
commands: opt -p loop-vectorize -S %s
opt -p loop-vectorize -prefer-predicate-over-epilogue=predicate-else-scalar-epilogue -S %s
tests: test_name: chained_recurrences
test_body: target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx14.0.0"

define i32 @chained_recurrences(i32 %x, i64 %y, ptr %src.1, i32 %z, ptr %src.2) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %0 = phi i32 [ 0, %entry ], [ %3, %loop ]
  %1 = phi i32 [ 0, %entry ], [ %0, %loop ]
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %sum.red = phi i32 [ 0, %entry ], [ %red.2, %loop ]
  %2 = add i64 %y, 1
  %gep.1 = getelementptr i32, ptr %src.1, i64 %2
  %3 = load i32, ptr %gep.1, align 4
  %or3 = or i32 %1, %x
  %iv.next = add i64 %iv, 1
  %shr = lshr i32 %x, 1
  %4 = shl i32 %or3, 1
  %5 = or i32 %4, 2
  %shl19 = shl i32 %x, 1
  %6 = or i32 %shr, %shl19
  %7 = or i32 %6, %5
  %8 = or i32 %7, %x
  %or20 = or i32 %z, %x
  %not = and i32 %or20, 1
  %and = xor i32 %not, 1
  %idx.ext.1 = zext i32 %and to i64
  %gep.2 = getelementptr i32, ptr %src.2, i64 %idx.ext.1
  %9 = load i32, ptr %gep.2, align 4
  %shr24 = lshr i32 %8, 1
  %idx.ext.2 = zext i32 %shr24 to i64
  %gep.3 = getelementptr i32, ptr %src.2, i64 %idx.ext.2
  %10 = load i32, ptr %gep.3, align 4
  %red.1 = or i32 %9, %sum.red
  %red.2 = or i32 %red.1, %10
  %ec = icmp eq i64 %iv, %y
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i32 %red.2
}

attributes #0 = { "target-features"="+sve" }

file: llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains.ll
commands: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s
tests: test_name: test_resinking_required
test_body: define double @test_resinking_required(ptr %p, ptr noalias %a, ptr noalias %b) {
Entry:
  br label %Loop

Loop:                                             ; preds = %Loop, %Entry
  %for.1 = phi double [ %l1, %Loop ], [ 0.000000e+00, %Entry ]
  %for.2 = phi double [ %l2, %Loop ], [ 0.000000e+00, %Entry ]
  %for.3 = phi double [ %for.2, %Loop ], [ 0.000000e+00, %Entry ]
  %iv = phi i64 [ %iv.next, %Loop ], [ 0, %Entry ]
  %USE_2_FORS = fdiv double %for.3, %for.1
  %div = fdiv double 0.000000e+00, %for.1
  %l1 = load double, ptr %a, align 8
  %iv.next = add nuw nsw i64 %iv, 1
  %l2 = load double, ptr %b, align 8
  store double %div, ptr %p, align 8
  %cond = icmp eq i64 %iv.next, 0
  br i1 %cond, label %End, label %Loop

End:                                              ; preds = %Loop
  %res.1 = fadd double %for.1, %for.2
  %res.2 = fadd double %res.1, %for.3
  ret double %res.2
}

file: llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll
commands: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s
tests: test_name: instruction_with_2_FOR_operands_and_multiple_other_uses_chain
test_body: define void @instruction_with_2_FOR_operands_and_multiple_other_uses_chain(ptr noalias %dst.1, ptr noalias %dst.2, ptr noalias %dst.3, ptr noalias %for.ptr.1, ptr noalias %for.ptr.2) {
bb:
  br label %loop

loop:                                             ; preds = %loop, %bb
  %for.1 = phi float [ 0.000000e+00, %bb ], [ %for.1.next, %loop ]
  %for.2 = phi float [ 0.000000e+00, %bb ], [ %for.2.next, %loop ]
  %iv = phi i64 [ 0, %bb ], [ %iv.next, %loop ]
  %for.1.use.1 = fmul fast float %for.1, 2.000000e+00
  %for.1.use.c = fmul fast float %for.1.use.1, 2.000000e+00
  %used.by.both = fmul fast float %for.1.use.c, %for.2
  %for.2.next = load float, ptr %for.ptr.2, align 4
  %for.1.use.3 = fadd fast float %for.1, 1.000000e+00
  %iv.next = add nuw nsw i64 %iv, 1
  %for.1.next = load float, ptr %for.ptr.1, align 4
  %gep.dst.1 = getelementptr inbounds float, ptr %dst.1, i64 %iv
  store float %used.by.both, ptr %gep.dst.1, align 4
  %gep.dst.2 = getelementptr inbounds float, ptr %dst.2, i64 %iv
  store float %for.1.use.1, ptr %gep.dst.2, align 4
  %gep.dst.3 = getelementptr inbounds float, ptr %dst.3, i64 %iv
  store float %for.1.use.3, ptr %gep.dst.3, align 4
  %ec = icmp slt i64 %iv, 1000
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

test_name: instruction_with_2_FOR_operands_and_multiple_other_uses
test_body: define void @instruction_with_2_FOR_operands_and_multiple_other_uses(ptr noalias %dst.1, ptr noalias %dst.2, ptr noalias %dst.3, ptr noalias %for.ptr.1, ptr noalias %for.ptr.2) {
bb:
  br label %loop

loop:                                             ; preds = %loop, %bb
  %for.1 = phi float [ 0.000000e+00, %bb ], [ %for.1.next, %loop ]
  %for.2 = phi float [ 0.000000e+00, %bb ], [ %for.2.next, %loop ]
  %iv = phi i64 [ 0, %bb ], [ %iv.next, %loop ]
  %for.1.use.1 = fmul fast float %for.1, 2.000000e+00
  %used.by.both = fmul fast float %for.1, %for.2
  %for.2.next = load float, ptr %for.ptr.2, align 4
  %for.1.use.3 = fadd fast float %for.1, 1.000000e+00
  %iv.next = add nuw nsw i64 %iv, 1
  %for.1.next = load float, ptr %for.ptr.1, align 4
  %gep.dst.1 = getelementptr inbounds float, ptr %dst.1, i64 %iv
  store float %used.by.both, ptr %gep.dst.1, align 4
  %gep.dst.2 = getelementptr inbounds float, ptr %dst.2, i64 %iv
  store float %for.1.use.1, ptr %gep.dst.2, align 4
  %gep.dst.3 = getelementptr inbounds float, ptr %dst.3, i64 %iv
  store float %for.1.use.3, ptr %gep.dst.3, align 4
  %ec = icmp slt i64 %iv, 1000
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

test_name: instruction_with_2_FOR_operands
test_body: define void @instruction_with_2_FOR_operands(ptr noalias %A, ptr noalias %B, ptr noalias %C) {
bb:
  br label %bb13

bb13:                                             ; preds = %bb13, %bb
  %tmp37 = phi float [ %tmp60, %bb13 ], [ 0.000000e+00, %bb ]
  %tmp27 = phi float [ %tmp49, %bb13 ], [ 1.000000e+00, %bb ]
  %iv = phi i64 [ %iv.next, %bb13 ], [ 0, %bb ]
  %tmp38 = fmul fast float %tmp37, %tmp27
  %iv.next = add nuw nsw i64 %iv, 1
  %gep = getelementptr inbounds float, ptr %C, i64 %iv
  %tmp49 = load float, ptr %A, align 4
  %tmp60 = load float, ptr %B, align 4
  store float %tmp38, ptr %gep, align 4
  %tmp12 = icmp slt i64 %iv, 1000
  br i1 %tmp12, label %bb13, label %bb74

bb74:                                             ; preds = %bb13
  ret void
}

file: llvm/test/Transforms/LoopVectorize/first-order-recurrence-multiply-recurrences.ll
tests: test_name: test_pr54233_for_depend_on_each_other
test_body: define void @test_pr54233_for_depend_on_each_other(ptr noalias %a, ptr noalias %b) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %for.1 = phi i32 [ 0, %entry ], [ %for.1.next, %loop ]
  %for.2 = phi i32 [ 0, %entry ], [ %for.2.next, %loop ]
  %or = or i32 %for.2, 10
  %shl = shl i32 %for.2, %for.1
  %xor = xor i32 %shl, 255
  %and = and i32 %xor, %or
  %for.1.next = xor i32 12, %for.2
  %for.2.next = load i32, ptr %b, align 4
  %a.gep = getelementptr inbounds i32, ptr %a, i64 %iv
  store i32 %and, ptr %a.gep, align 4
  %iv.next = add nuw i64 %iv, 1
  %exitcond = icmp eq i64 %iv, 1000
  br i1 %exitcond, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

test_name: test_pr54223_sink_after_insertion_order
test_body: define void @test_pr54223_sink_after_insertion_order(ptr noalias %a, ptr noalias %b, ptr noalias %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %for.1 = phi float [ 0.000000e+00, %entry ], [ %for.1.next, %loop ]
  %for.2 = phi float [ 0.000000e+00, %entry ], [ %for.2.next, %loop ]
  %neg = fneg float %for.2
  %muladd = call float @llvm.fmuladd.f32(float %for.1, float %neg, float 0.000000e+00)
  %dst.gep = getelementptr inbounds float, ptr %dst, i64 %iv
  %iv.next = add nuw nsw i64 %iv, 1
  %for.1.next = load float, ptr %a, align 4
  %for.2.next = load float, ptr %b, align 4
  store float %muladd, ptr %dst.gep, align 4
  %exitcond.not = icmp eq i64 %iv.next, 10000
  br i1 %exitcond.not, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare float @llvm.fmuladd.f32(float, float, float) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

file: llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll
commands: opt < %s -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=2 -force-widen-divrem-via-safe-divisor=0 -S
opt < %s -passes=loop-vectorize -force-vector-width=1 -force-vector-interleave=2 -force-widen-divrem-via-safe-divisor=0 -S
opt < %s -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -force-widen-divrem-via-safe-divisor=0 -S
tests: test_name: recurence_uniform_load
test_body: target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"

define i32 @recurence_uniform_load(ptr %src, ptr noalias %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %phi = phi i64 [ 0, %entry ], [ %add, %loop ]
  %recur = phi i32 [ 0, %entry ], [ %load, %loop ]
  %add = add i64 %phi, 1
  %load = load i32, ptr %src, align 4
  %icmp = icmp ult i64 %phi, 1
  br i1 %icmp, label %loop, label %exit

exit:                                             ; preds = %loop
  ret i32 0
}