commit 99685a54d1322694847f59386a548b3696a43fc3
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Sat Jul 13 04:27:07 2024 +0800

    [MemCpyOpt] Use `dyn_cast` to fix assertion failure in `processMemCpyMemCpyDependence` (#98686)

    Fixes https://github.com/llvm/llvm-project/issues/98675.

diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 1c65219585e5..4063762c88a2 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1188,9 +1188,9 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
     if (MDestOffset == MForwardOffset)
       CopySource = M->getDest();
     else {
-      NewCopySource = cast<Instruction>(Builder.CreateInBoundsPtrAdd(
-          CopySource, Builder.getInt64(MForwardOffset)));
-      CopySource = NewCopySource;
+      CopySource = Builder.CreateInBoundsPtrAdd(
+          CopySource, Builder.getInt64(MForwardOffset));
+      NewCopySource = dyn_cast<Instruction>(CopySource);
     }
     // We need to update `MCopyLoc` if an offset exists.
     MCopyLoc = MCopyLoc.getWithNewPtr(CopySource);

opt < %s -passes=memcpyopt -S -verify-memoryssa

define void @do_not_forward_offset_and_store(ptr %src, ptr %dest) {
  %cpy_tmp = alloca [9 x i8], align 1
  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false)
  %src_offset = getelementptr inbounds i8, ptr %src, i64 1
  store i8 1, ptr %src_offset, align 1
  %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1
  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 5, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

@buf = external global [32 x i8]

define void @pr98675(ptr noalias %p1, ptr noalias %p2) {
  call void @llvm.memcpy.p0.p0.i64(ptr %p1, ptr @buf, i64 26, i1 false)
  %gep = getelementptr i8, ptr %p1, i64 10
  call void @llvm.memmove.p0.p0.i64(ptr %p2, ptr %gep, i64 1, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg) #0

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

[MemCpyOpt] Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

Detected by https://github.com/dtcxzyw/llvm-opt-benchmark/issues/935.

Reproducer:
```
; bin/opt -passes=memcpyopt -S test.ll
@b = external global [32 x i8]

define void @_Z15TestBasicStringIN5eastl12basic_stringIc17CountingAllocatorEEEiv(ptr %call.i.i.i12866) {
  %a = alloca [32 x i8], align 1
  call void @llvm.memcpy.p0.p0.i64(ptr %call.i.i.i12866, ptr @b, i64 26, i1 false)
  %.sroa.gep22184 = getelementptr i8, ptr %call.i.i.i12866, i64 10
  call void @llvm.memmove.p0.p0.i64(ptr %a, ptr %.sroa.gep22184, i64 1, i1 false)
  ret void
}
```
```
opt: /home/dtcxzyw/WorkSpace/Projects/compilers/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = Instruction; From = Value]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/opt -passes=memcpyopt reduced.ll
1.      Running pass "function(memcpyopt)" on module "reduced.ll"
2.      Running pass "memcpyopt" on function "_Z15TestBasicStringIN5eastl12basic_stringIc17CountingAllocatorEEEiv"
 #0 0x00007e04ebe0c9c2 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.19.0git+0x20c9c2)
 #1 0x00007e04ebe0988f llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.19.0git+0x20988f)
 #2 0x00007e04ebe099d5 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007e04eb842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007e04eb8969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007e04eb8969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007e04eb8969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007e04eb842476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007e04eb8287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007e04eb82871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007e04eb839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00007e04e5ab5dfa llvm::MemCpyOptPass::processMemCpyMemCpyDependence(llvm::MemCpyInst*, llvm::MemCpyInst*, llvm::BatchAAResults&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMScalarOpts.so.19.0git+0x2b5dfa)
#12 0x00007e04e5abd2aa llvm::MemCpyOptPass::processMemCpy(llvm::MemCpyInst*, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void, true, llvm::BasicBlock>, false, false>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMScalarOpts.so.19.0git+0x2bd2aa)
#13 0x00007e04e5abd9c4 llvm::MemCpyOptPass::iterateOnFunction(llvm::Function&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMScalarOpts.so.19.0git+0x2bd9c4)
#14 0x00007e04e5abdcce llvm::MemCpyOptPass::runImpl(llvm::Function&, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::AssumptionCache*, llvm::DominatorTree*, llvm::PostDominatorTree*, llvm::MemorySSA*) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMScalarOpts.so.19.0git+0x2bdcce)
#15 0x00007e04e5abe15c llvm::MemCpyOptPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMScalarOpts.so.19.0git+0x2be15c)
#16 0x00007e04e74cde55 llvm::detail::PassModel<llvm::Function, llvm::MemCpyOptPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMPasses.so.19.0git+0xcde55)
#17 0x00007e04e474b7b2 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.19.0git+0x34b7b2)
#18 0x00007e04eaad5065 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.19.0git+0xd5065)
#19 0x00007e04e474a40e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.19.0git+0x34a40e)
#20 0x00007e04eaad5985 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.19.0git+0xd5985)
#21 0x00007e04e47483da llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.19.0git+0x3483da)
#22 0x00007e04ec103267 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) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.19.0git+0x2d267)
#23 0x00007e04ec10f212 optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.19.0git+0x39212)
#24 0x00007e04eb829d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#25 0x00007e04eb829e40 call_init ./csu/../csu/libc-start.c:128:20
#26 0x00007e04eb829e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#27 0x00005df852081095 _start (bin/opt+0x1095)
Aborted (core dumped)
```

This issue is caused by https://github.com/llvm/llvm-project/commit/fa2421392802025e842454a31ed50dbfab643130.
https://github.com/llvm/llvm-project/blob/d1dc5047f1127d64eb82eec976fabaa2d9d20c11/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp#L1191-L1192
`Builder.CreateInBoundsPtrAdd` may return `GetElementPtrConstantExpr`.

cc @nikic @DianQK

It looks similar to https://lab.llvm.org/buildbot/#/builders/41/builds/587. I really shouldn't have merged the code before going to bed :3


commit fc9cd3272b50f4ee9f18c4ab82c278bbb014d99f
Author: Florian Hahn <flo@fhahn.com>
Date:   Sun Jul 14 20:49:03 2024 +0100

    [VPlan] Don't add live-outs for IV phis.

    Resume and exit values for inductions are currently still created
    outside of VPlan and independent of the induction recipes. Don't add
    live-outs for now, as the additional unneeded users can pessimize other
    anlysis.

    Fixes https://github.com/llvm/llvm-project/issues/98660.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 7d37d67cde29..5520baef7152 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8693,6 +8693,14 @@ static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop,
     Value *IncomingValue =
         ExitPhi.getIncomingValueForBlock(ExitingBB);
     VPValue *V = Builder.getVPValueOrAddLiveIn(IncomingValue, Plan);
+    // Exit values for inductions are computed and updated outside of VPlan and
+    // independent of induction recipes.
+    // TODO: Compute induction exit values in VPlan, use VPLiveOuts to update
+    // live-outs.
+    if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
+         !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst()) ||
+        isa<VPWidenPointerInductionRecipe>(V))
+      continue;
     Plan.addLiveOut(&ExitPhi, V);
   }
 }

opt -passes=loop-vectorize -mtriple=aarch64-unknown -mattr=+sve -S %s

define ptr @test(ptr %start.1, ptr %start.2, ptr %end) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv.1 = phi ptr [ %start.1, %entry ], [ %iv.1.next, %loop ]
  %iv.2 = phi ptr [ %start.2, %entry ], [ %iv.2.next, %loop ]
  store i64 0, ptr %iv.2, align 4
  %iv.2.next = getelementptr inbounds ptr, ptr %iv.2, i64 1
  %iv.1.next = getelementptr inbounds ptr, ptr %iv.1, i64 1
  %cmp.i.i.not.i = icmp eq ptr %iv.2.next, %end
  br i1 %cmp.i.i.not.i, label %exit, label %loop

exit:                                             ; preds = %loop
  %res.lcssa = phi ptr [ %iv.1, %loop ]
  ret ptr %res.lcssa
}

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx"

define i32 @ephemeral_load_and_compare_iv_used_outside(ptr %start, ptr %end) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi ptr [ %start, %entry ], [ %iv.next, %loop ]
  %iv.next = getelementptr nusw i8, ptr %iv, i64 -8
  %l1 = load i32, ptr %iv, align 4
  %cmp = icmp ne i32 %l1, 0
  call void @llvm.assume(i1 %cmp)
  %cmp.not = icmp eq ptr %iv, %end
  br i1 %cmp.not, label %exit, label %loop

exit:                                             ; preds = %loop
  %final.load = load i32, ptr %iv, align 4
  ret i32 %final.load
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #1

attributes #0 = { "target-cpu"="skylake-avx512" }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

opt -p loop-vectorize -mcpu=skylake-avx512 -S %s

target triple = "x86_64-unknown-linux-gnu"

define i64 @test_pr98660(ptr %dst, i64 %N) {
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %or = or disjoint i64 %iv, 1
  %gep = getelementptr i32, ptr %dst, i64 %or
  %l = load i32, ptr %gep
  %c = icmp eq i32 %l, 0
  br i1 %c, label %then, label %loop.latch

then:
  store i32 0, ptr %gep, align 4
  br label %loop.latch

loop.latch:
  %iv.next = add i64 %iv, 1
  %ec = icmp ult i64 %iv, %N
  br i1 %ec, label %loop.header, label %exit

exit:
  %ret = phi i64 [ %iv, %loop.latch ]
  ret i64 %ret
}
;.
;.

opt -S -passes=loop-vectorize -force-vector-interleave=1 -force-vector-width=2 < %s

opt -S -passes=loop-vectorize -force-vector-interleave=2 -force-vector-width=1 < %s

define i32 @iv_2_dead_in_loop_only_used_outside(ptr %ptr) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %iv.2 = phi i32 [ 0, %entry ], [ %iv.2.next, %loop ]
  %iv.next = add nuw i64 %iv, 1
  %iv.2.next = add nuw i32 %iv.2, 2
  %gep.ptr = getelementptr inbounds i64, ptr %ptr, i64 %iv
  store i64 %iv, ptr %gep.ptr, align 4
  %exitcond = icmp ugt i64 %iv, 1000
  br i1 %exitcond, label %exit, label %loop

exit:                                             ; preds = %loop
  %iv.2.lcssa = phi i32 [ %iv.2, %loop ]
  ret i32 %iv.2.lcssa
}

opt < %s -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S

define i32 @test(ptr %arr, i64 %n) {
entry:
  %cmp1 = icmp ugt i64 %n, 1
  br i1 %cmp1, label %preheader, label %done

preheader:                                        ; preds = %entry
  br label %loop

loop:                                             ; preds = %loop, %preheader
  %conv = phi i64 [ %conv2, %loop ], [ 1, %preheader ]
  %i = phi i8 [ %inc, %loop ], [ 1, %preheader ]
  %sub = add nsw i64 %conv, -1
  %ptr = getelementptr inbounds i32, ptr %arr, i64 %sub
  store i32 65, ptr %ptr, align 4
  %inc = add i8 %i, 1
  %conv2 = zext i8 %inc to i64
  %cmp2 = icmp ult i64 %conv2, %n
  br i1 %cmp2, label %loop, label %load_val, !llvm.loop !0

load_val:                                         ; preds = %loop
  %final = phi i64 [ %conv, %loop ]
  %ptr2 = getelementptr inbounds i32, ptr %arr, i64 %final
  %val = load i32, ptr %ptr2, align 4
  br label %done

done:                                             ; preds = %load_val, %entry
  %value = phi i32 [ %val, %load_val ], [ 0, %entry ]
  ret i32 %value
}

!0 = distinct !{!0, !1, !2, !3}
!1 = !{!"llvm.loop.unroll.disable"}
!2 = !{!"llvm.loop.vectorize.predicate.enable", i1 true}
!3 = !{!"llvm.loop.vectorize.enable", i1 true}

opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s

define void @test1_pr58811() {
entry:
  br label %loop.1.preheader

loop.1.preheader:                                 ; preds = %unreachable.bb, %entry
  %iv.1.ph = phi i32 [ %sub93.2, %unreachable.bb ], [ 0, %entry ]
  br label %loop.1

loop.1:                                           ; preds = %loop.1, %loop.1.preheader
  %iv.1 = phi i32 [ %iv.1.next, %loop.1 ], [ %iv.1.ph, %loop.1.preheader ]
  %iv.2 = phi i32 [ %iv.2.next, %loop.1 ], [ 0, %loop.1.preheader ]
  %iv.2.next = add i32 %iv.2, 1
  %iv.1.next = add i32 %iv.2, %iv.1
  br i1 false, label %loop.1, label %loop.2.preheader

loop.2.preheader:                                 ; preds = %loop.1
  %iv.1.lcssa = phi i32 [ %iv.1, %loop.1 ]
  br label %loop.2

loop.2:                                           ; preds = %loop.2, %loop.2.preheader
  %iv.3 = phi i16 [ %iv.3.next, %loop.2 ], [ 0, %loop.2.preheader ]
  %iv.4 = phi i32 [ %iv.4.next, %loop.2 ], [ 0, %loop.2.preheader ]
  %iv.4.next = sub i32 %iv.4, %iv.1.lcssa
  %iv.3.next = add i16 %iv.3, 1
  %cmp88.1 = icmp ult i16 %iv.3, 198
  br i1 %cmp88.1, label %loop.2, label %loop.3.preheader

loop.3.preheader:                                 ; preds = %loop.2
  %iv.4.lcssa = phi i32 [ %iv.4, %loop.2 ]
  br label %loop.3

loop.3:                                           ; preds = %loop.3, %loop.3.preheader
  %iv.5 = phi i32 [ %sub93.2, %loop.3 ], [ 0, %loop.3.preheader ]
  %sub93.2 = sub i32 %iv.5, %iv.4.lcssa
  br label %loop.3

unreachable.bb:                                   ; No predecessors!
  br label %loop.1.preheader
}

define void @test2_pr58811() {
entry:
  br label %loop.1.header

loop.1.header:                                    ; preds = %loop.4, %entry
  %p.1 = phi i32 [ 0, %entry ], [ %sub93.2, %loop.4 ]
  br label %loop.2

loop.2:                                           ; preds = %loop.2, %loop.1.header
  %iv.2 = phi i32 [ %p.1, %loop.1.header ], [ %add101, %loop.2 ]
  %iv.3 = phi i32 [ 0, %loop.1.header ], [ %sub93, %loop.2 ]
  %sub93 = add i32 %iv.3, 1
  %add101 = add i32 %iv.3, %iv.2
  br i1 false, label %loop.2, label %loop.3

loop.3:                                           ; preds = %loop.3, %loop.2
  %iv.4 = phi i16 [ 0, %loop.2 ], [ %inc.1, %loop.3 ]
  %iv.5 = phi i32 [ 0, %loop.2 ], [ %sub93.1, %loop.3 ]
  %sub93.1 = sub i32 %iv.5, %iv.2
  %inc.1 = add i16 %iv.4, 1
  %cmp88.1 = icmp ult i16 %iv.4, 198
  br i1 %cmp88.1, label %loop.3, label %loop.4

loop.4:                                           ; preds = %loop.4, %loop.3
  %iv.6 = phi i32 [ 0, %loop.3 ], [ %sub93.2, %loop.4 ]
  %sub93.2 = sub i32 %iv.6, %iv.5
  br i1 false, label %loop.4, label %loop.1.header
}

define void @test3_pr58811() {
entry:
  br label %loop.1.header

loop.1.header:                                    ; preds = %loop.1.latch, %entry
  %p.1 = phi i32 [ 0, %entry ], [ %sub93.2, %loop.1.latch ]
  %rem85 = urem i32 1, %p.1
  br label %loop.2

loop.2:                                           ; preds = %loop.2, %loop.1.header
  %p.2 = phi i32 [ 1, %loop.1.header ], [ 0, %loop.2 ]
  %add101 = add i32 %rem85, %p.2
  br i1 false, label %loop.2, label %loop.3

loop.3:                                           ; preds = %loop.3, %loop.2
  %iv.3 = phi i16 [ 0, %loop.2 ], [ %inc.1, %loop.3 ]
  %iv.4 = phi i32 [ 0, %loop.2 ], [ %sub93.1, %loop.3 ]
  %sub93.1 = sub i32 %iv.4, %add101
  %inc.1 = add i16 %iv.3, 1
  %cmp88.1 = icmp ult i16 %iv.3, 198
  br i1 %cmp88.1, label %loop.3, label %loop.4

loop.4:                                           ; preds = %loop.4, %loop.3
  %iv.5 = phi i32 [ 0, %loop.3 ], [ %sub93.2, %loop.4 ]
  %sub93.2 = sub i32 %iv.5, %iv.4
  br label %loop.4

loop.1.latch:                                     ; No predecessors!
  br label %loop.1.header
}

Assertion `(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 " "per part."' failed.

To reproduce run opt opt with -passes loop-vectorize with the following test:
```
; 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 void @wombat(i64 %arg) #0 gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i64 [ 0, %bb ], [ %add, %bb3 ]
  br i1 false, label %bb2, label %bb3

bb2:                                              ; preds = %bb1
  %or = or disjoint i64 %phi, 0
  %getelementptr = getelementptr i32, ptr addrspace(1) null, i64 %or
  store i32 0, ptr addrspace(1) %getelementptr, align 4
  br label %bb3

bb3:                                              ; preds = %bb2, %bb1
  %add = add i64 %phi, 1
  %icmp = icmp ult i64 %phi, %arg
  br i1 %icmp, label %bb1, label %bb4

bb4:                                              ; preds = %bb3
  %phi5 = phi i64 [ %phi, %bb3 ]
  ret void
}

attributes #0 = { "target-features"="+prfchw,-cldemote,+avx,+aes,+sahf,+pclmul,-xop,+crc32,+xsaves,-avx512fp16,-usermsr,-sm4,-egpr,+sse4.1,-avx512ifma,+xsave,+sse4.2,-tsxldtrk,-sm3,-ptwrite,-widekl,+invpcid,+64bit,+xsavec,-avx10.1-512,-avx512vpopcntdq,+cmov,-avx512vp2intersect,+avx512cd,+movbe,-avxvnniint8,-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,-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,-avx512f" }
```
Reproducer:
https://godbolt.org/z/Ghz3147nj

Stack dump:
```
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes loop-vectorize <source>
1.	Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "<source>"
2.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "wombat"
 #0 0x0000000004e9b948 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e9b948)
 #1 0x0000000004e990bc SignalHandler(int) Signals.cpp:0:0
 #2 0x000070edf8442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000070edf84969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000070edf8442476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000070edf84287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000070edf842871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000070edf8439e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x00000000040395f7 llvm::VPTransformState::get(llvm::VPValue*, unsigned int, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40395f7)
 #9 0x0000000004056ece llvm::VPInstruction::generatePerPart(llvm::VPTransformState&, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4056ece)
#10 0x00000000040595ee llvm::VPInstruction::execute(llvm::VPTransformState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40595ee)
#11 0x0000000004030a1f llvm::VPBasicBlock::executeRecipes(llvm::VPTransformState*, llvm::BasicBlock*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4030a1f)
#12 0x00000000040320e8 llvm::VPBasicBlock::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40320e8)
#13 0x0000000004030612 llvm::VPRegionBlock::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4030612)
#14 0x0000000004039946 llvm::VPlan::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4039946)
#15 0x0000000003f1d475 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+0x3f1d475)
#16 0x0000000003f332ea llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3f332ea)
#17 0x0000000003f35a29 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+0x3f35a29)
#18 0x0000000003f3614b llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3f3614b)
#19 0x0000000002e212be 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+0x2e212be)
#20 0x0000000004c9f2d8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9f2d8)
#21 0x0000000000dc9bee 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+0xdc9bee)
#22 0x0000000004c9dd46 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9dd46)
#23 0x0000000000dca1fe 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+0xdca1fe)
#24 0x0000000004c9bf10 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9bf10)
#25 0x00000000008db1d2 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+0x8db1d2)
#26 0x00000000008ce0fc optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ce0fc)
#27 0x000070edf8429d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#28 0x000070edf8429e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#29 0x00000000008c556e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8c556e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Interesting, let me take a look


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 "

opt -S -passes=loop-vectorize -mcpu=skylake-avx512 -mtriple=x86_64-apple-macosx -S %s

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
}
;.
;.

New LLVM vectorizer crash in assertion

@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
```


commit 9304af3927caecdb43d3a9b5d16c6a5b7a6b5594
Author: Jorge Botto <23462171+jf-botto@users.noreply.github.com>
Date:   Fri Aug 9 11:52:56 2024 +0100

    [InstCombine] Fixing wrong select folding in vectors with undef elements (#102244)

    This PR fixes https://github.com/llvm/llvm-project/issues/98435.
    `SimplifyDemandedVectorElts` mishandles the undef by assuming that
    !isNullValue() means the condition is true.

    By preventing any value that we're not certain equals 1 or 0, it avoids
    having to make any particular choice by not demanding bits from a
    particular branch with potentially picking a wrong value.

    Proof: https://alive2.llvm.org/ce/z/r8CmEu

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index c494fec84c1e..153d8c238ed4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1735,17 +1735,12 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
     APInt DemandedLHS(DemandedElts), DemandedRHS(DemandedElts);
     if (auto *CV = dyn_cast<ConstantVector>(Sel->getCondition())) {
       for (unsigned i = 0; i < VWidth; i++) {
-        // isNullValue() always returns false when called on a ConstantExpr.
-        // Skip constant expressions to avoid propagating incorrect information.
         Constant *CElt = CV->getAggregateElement(i);
-        if (isa<ConstantExpr>(CElt))
-          continue;
-        // TODO: If a select condition element is undef, we can demand from
-        // either side. If one side is known undef, choosing that side would
-        // propagate undef.
+
+        // isNullValue() always returns false when called on a ConstantExpr.
         if (CElt->isNullValue())
           DemandedLHS.clearBit(i);
-        else
+        else if (CElt->isOneValue())
           DemandedRHS.clearBit(i);
       }
     }

define <2 x i1> @pr98435(<2 x i1> %val) {
  %val1 = select <2 x i1> <i1 undef, i1 true>, <2 x i1> splat (i1 true), <2 x i1> %val
  ret <2 x i1> %val1
}

Wrong select folding for undef conditions by InstCombine

https://github.com/llvm/llvm-project/blob/7eae9bb856135136cddc4208a2b1546e9db44c9c/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp#L3582-L3585

Alive2 report: https://alive2.llvm.org/ce/z/Qtu72J

```ll
----------------------------------------
define <2 x i1> @fun0(<2 x i1> %val0, <2 x i1> %val1) {
#0:
  %val2 = select <2 x i1> %val0, <2 x i1> %val0, <2 x i1> %val0
  %val3 = select <2 x i1> { undef, 1 }, <2 x i1> { 1, 1 }, <2 x i1> %val2
  ret <2 x i1> %val3
}
=>
define <2 x i1> @fun0(<2 x i1> %val0, <2 x i1> %val1) {
#0:
  ret <2 x i1> { poison, 1 }
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
<2 x i1> %val0 = < #x0 (0), #x0 (0) >
<2 x i1> %val1 = < #x0 (0), #x0 (0) >

Source:
<2 x i1> %val2 = < #x0 (0), #x0 (0) >
<2 x i1> %val3 = < #x0 (0)	[based on undef value], #x1 (1) >

Target:
Source value: < #x0 (0), #x1 (1) >
Target value: < poison, #x1 (1) >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```

Would this issue be to fix InstCombine to not try to optimise it or get InstCombine to pick  `<2 x i1> { 1, 1 }` because `undef` let's it pick either values and picking a constant vector is better than picking a variable?

The problematic step seems to be this one: https://alive2.llvm.org/ce/z/C2waWU

I don't think the quoted code is responsible for this, as it is guarded by `!isa<Constant>(CondVal)`.

I think the problem is with how `SimplifyDemandedVectorElts` handles the undef: https://github.com/llvm/llvm-project/blob/af80d3a248101d6f5d9d5e229c7899136b8ce0b8/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp#L1721-L1760

@jf-botto Agree. It assumes that !isNullValue() means "is true", which is not the case.


commit e31252bf54dedadfe78b36d07ea6084156faa38a
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Wed Aug 21 11:47:00 2024 -0700

    [SLP]Fix PR105120: fix the order of phi nodes vectorization.

    The operands of the phi nodes should be vectorized in the same order, in
    which they were created, otherwise the compiler may crash when trying
    to correctly build dependency for nodes with non-schedulable
    instructions for gather/buildvector nodes.

    Fixes https://github.com/llvm/llvm-project/issues/105120

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index dee6d688b1b9..848e0de20e7b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -7227,6 +7227,22 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,

   unsigned ShuffleOrOp = S.isAltShuffle() ?
                 (unsigned) Instruction::ShuffleVector : S.getOpcode();
+  auto CreateOperandNodes = [&](TreeEntry *TE, const auto &Operands) {
+    // Postpone PHI nodes creation
+    SmallVector<unsigned> PHIOps;
+    for (unsigned I : seq<unsigned>(Operands.size())) {
+      ArrayRef<Value *> Op = Operands[I];
+      if (Op.empty())
+        continue;
+      InstructionsState S = getSameOpcode(Op, *TLI);
+      if (S.getOpcode() != Instruction::PHI || S.isAltShuffle())
+        buildTree_rec(Op, Depth + 1, {TE, I});
+      else
+        PHIOps.push_back(I);
+    }
+    for (unsigned I : PHIOps)
+      buildTree_rec(Operands[I], Depth + 1, {TE, I});
+  };
   switch (ShuffleOrOp) {
     case Instruction::PHI: {
       auto *PH = cast<PHINode>(VL0);
@@ -7238,10 +7254,12 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
       // Keeps the reordered operands to avoid code duplication.
       PHIHandler Handler(*DT, PH, VL);
       Handler.buildOperands();
-      for (unsigned I : seq<unsigned>(0, PH->getNumOperands()))
+      for (unsigned I : seq<unsigned>(PH->getNumOperands()))
         TE->setOperand(I, Handler.getOperands(I));
-      for (unsigned I : seq<unsigned>(0, PH->getNumOperands()))
-        buildTree_rec(Handler.getOperands(I), Depth + 1, {TE, I});
+      SmallVector<ArrayRef<Value *>> Operands(PH->getNumOperands());
+      for (unsigned I : seq<unsigned>(PH->getNumOperands()))
+        Operands[I] = Handler.getOperands(I);
+      CreateOperandNodes(TE, Operands);
       return;
     }
     case Instruction::ExtractValue:

opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 < %s

define void @test() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i32 [ 0, %bb ], [ %add5, %bb3 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add, %bb3 ]
  br i1 false, label %bb6, label %bb3

bb3:                                              ; preds = %bb1
  %add = add i32 0, 0
  %add4 = add i32 0, 0
  %add5 = add i32 %phi, 0
  br i1 false, label %bb6, label %bb1

bb6:                                              ; preds = %bb3, %bb1
  %phi7 = phi i32 [ %phi2, %bb1 ], [ %add4, %bb3 ]
  %phi8 = phi i32 [ %phi, %bb1 ], [ %add5, %bb3 ]
  ret void
}

[SLPVectorizer] Instruction does not dominate all uses! LLVM ERROR: Broken module found, compilation aborted!

To reproduce run the test below with -passes slp-vectorizer -slp-threshold=-99999
```
; 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 void @wombat() #0 gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i32 [ 0, %bb ], [ %add5, %bb3 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add, %bb3 ]
  br i1 false, label %bb6, label %bb3

bb3:                                              ; preds = %bb1
  %add = add i32 0, 0
  %add4 = add i32 0, 0
  %add5 = add i32 %phi, 0
  br i1 false, label %bb6, label %bb1

bb6:                                              ; preds = %bb3, %bb1
  %phi7 = phi i32 [ %phi2, %bb1 ], [ %add4, %bb3 ]
  %phi8 = phi i32 [ %phi, %bb1 ], [ %add5, %bb3 ]
  ret void
}
```
Reproducer: https://godbolt.org/z/W96s5a1cb

```
Instruction does not dominate all uses!
  %2 = shufflevector <2 x i32> %0, <2 x i32> <i32 0, i32 poison>, <2 x i32> <i32 2, i32 1>
  %1 = add <2 x i32> zeroinitializer, %2
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes slp-vectorizer -slp-threshold=-99999 <source>
1.	Running pass "verify" on module "<source>"
 #0 0x0000000004f84b88 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f84b88)
 #1 0x0000000004f822fc SignalHandler(int) Signals.cpp:0:0
 #2 0x000074dcb3642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000074dcb36969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000074dcb3642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000074dcb36287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00000000007b7cc5 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x0000000004ebea18 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ebea18)
 #8 0x0000000004dbae20 llvm::VerifierPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4dbae20)
 #9 0x00000000008dbbde llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8dbbde)
#10 0x0000000004d7ebb0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4d7ebb0)
#11 0x00000000008e6912 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+0x8e6912)
#12 0x00000000008d97ec optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d97ec)
#13 0x000074dcb3629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x000074dcb3629e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x00000000008d127e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d127e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Yes


commit 533e6bbd0d344a710c491a9eb0ce0ba0852b08cb
Author: Florian Hahn <flo@fhahn.com>
Date:   Mon Aug 26 09:15:58 2024 +0100

    [VPlan] Simplify live-ins if they are SCEVConstant.

    The legacy cost model in some parts checks if any of the operands are
    constants via SCEV. Update VPlan construction to replace live-ins that
    are constants via SCEV with such constants. This means VPlans (and
    codegen) reflects what we computing the cost of and removes another case
    where the legacy and VPlan cost model diverged.

    Fixes https://github.com/llvm/llvm-project/issues/105722.

diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
index 0b27933925d8..0fbdeeddaf4a 100644
--- a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
+++ b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
@@ -13,6 +13,7 @@
 #include "VPlan.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerUnion.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
 #include "llvm/IR/IRBuilder.h"

 namespace llvm {
@@ -173,6 +174,11 @@ public:
       if (auto *R = Ingredient2Recipe.lookup(I))
         return R->getVPSingleValue();
     }
+    ScalarEvolution &SE = *PSE.getSE();
+    if (!isa<Constant>(V) && SE.isSCEVable(V->getType()))
+      if (auto *C = dyn_cast<SCEVConstant>(PSE.getSE()->getSCEV(V)))
+        return Plan.getOrAddLiveIn(C->getValue());
+
     return Plan.getOrAddLiveIn(V);
   }
 };

opt < %s -passes=loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -S

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define i64 @cost_assume(ptr %end, i64 %N) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %0 = phi i64 [ 0, %entry ], [ %1, %loop ]
  %1 = add i64 %0, 1
  %iv.next = add nsw i64 %iv, 1
  %c = icmp ne i64 %N, 0
  tail call void @llvm.assume(i1 %c)
  %gep = getelementptr nusw [9 x i8], ptr null, i64 %iv.next
  %ec = icmp eq ptr %gep, %end
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i64 %1
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

@c = external global [2048 x i32], align 16
@b = external global [2048 x i32], align 16
@d = external global [2048 x i32], align 16
@a = external global [2048 x i32], align 16

; Function Attrs: noinline nounwind ssp uwtable
define void @cost_model_1() #0 {
entry:
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  %0 = shl nsw i64 %indvars.iv, 1
  %arrayidx = getelementptr inbounds [2048 x i32], ptr @c, i64 0, i64 %0
  %1 = load i32, ptr %arrayidx, align 8
  %idxprom1 = sext i32 %1 to i64
  %arrayidx2 = getelementptr inbounds [2048 x i32], ptr @b, i64 0, i64 %idxprom1
  %2 = load i32, ptr %arrayidx2, align 4
  %arrayidx4 = getelementptr inbounds [2048 x i32], ptr @d, i64 0, i64 %indvars.iv
  %3 = load i32, ptr %arrayidx4, align 4
  %idxprom5 = sext i32 %3 to i64
  %arrayidx6 = getelementptr inbounds [2048 x i32], ptr @a, i64 0, i64 %idxprom5
  store i32 %2, ptr %arrayidx6, align 4
  %indvars.iv.next = add i64 %indvars.iv, 1
  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
  %exitcond = icmp eq i32 %lftr.wideiv, 256
  br i1 %exitcond, label %for.end, label %for.body

for.end:                                          ; preds = %for.body
  ret void
}

attributes #0 = { noinline nounwind ssp uwtable }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define i64 @avx512_cond_load_cost(ptr %src, i32 %a, i64 %b, i32 %c, i32 %d) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %c.1 = icmp slt i32 %iv, 0
  br i1 %c.1, label %if.then, label %loop.latch

if.then:                                          ; preds = %loop.header
  %0 = urem i32 %a, %c
  %mul = sub i32 0, %0
  %div = udiv i32 %c, %d
  %or = or i32 %div, %mul
  %ext = sext i32 %or to i64
  %gep = getelementptr { i64, i64, i64 }, ptr %src, i64 %ext, i32 2
  %l = load i64, ptr %gep, align 8
  %or.2 = or i64 %l, %b
  br label %loop.latch

loop.latch:                                       ; preds = %if.then, %loop.header
  %res = phi i64 [ 0, %loop.header ], [ %or.2, %if.then ]
  %iv.next = add i32 %iv, 1
  %ec = icmp ult i32 %iv, %c
  br i1 %ec, label %loop.header, label %exit

exit:                                             ; preds = %loop.latch
  ret i64 %res
}

attributes #0 = { "target-features"="+avx512bw,+avx512cd,+avx512dq,+avx512f,+avx512vl" }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define void @multi_exit(ptr %dst, ptr %src.1, ptr %src.2, i64 %A, i64 %B) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop.latch, %entry
  %iv.1.wide = phi i64 [ 0, %entry ], [ %iv.1.next.wide, %loop.latch ]
  %iv.1 = phi i32 [ 0, %entry ], [ %iv.1.next, %loop.latch ]
  %ec.1 = icmp ult i64 %iv.1.wide, %A
  br i1 %ec.1, label %loop.latch, label %exit

loop.latch:                                       ; preds = %loop
  %l.1 = load i64, ptr %src.1, align 8
  %l.2 = load i64, ptr %src.2, align 8
  %cmp55.us = icmp eq i64 %l.1, 0
  %cmp.i.us = icmp ne i64 %l.2, 0
  %and = and i1 %cmp.i.us, %cmp55.us
  %ext = zext i1 %and to i8
  store i8 %ext, ptr %dst, align 1
  %iv.1.next = add i32 %iv.1, 1
  %iv.1.next.wide = zext i32 %iv.1.next to i64
  %ec.2 = icmp ult i64 %iv.1.next.wide, %B
  br i1 %ec.2, label %loop, label %exit

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

attributes #0 = { "target-cpu"="penryn" }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define void @cost_duplicate_recipe_for_sinking(ptr %A, i64 %N) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %iv.shl = shl nsw i64 %iv, 2
  %gep.0 = getelementptr nusw double, ptr %A, i64 %iv.shl
  %l = load double, ptr %gep.0, align 8
  %c = fcmp oeq double %l, 0.000000e+00
  br i1 %c, label %if.then, label %loop.latch

if.then:                                          ; preds = %loop.header
  %gep.1 = getelementptr double, ptr %A, i64 %iv.shl
  store double 0.000000e+00, ptr %gep.1, align 8
  br label %loop.latch

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

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

attributes #0 = { "target-cpu"="znver3" }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define i1 @any_of_cost(ptr %start, ptr %end) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %any.of = phi i1 [ false, %entry ], [ %any.of.next, %loop ]
  %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop ]
  %gep = getelementptr i8, ptr %ptr.iv, i64 8
  %l = load ptr, ptr %gep, align 8
  %cmp13.not.not = icmp eq ptr %l, null
  %any.of.next = select i1 %cmp13.not.not, i1 %any.of, i1 false
  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 40
  %cmp.not = icmp eq ptr %ptr.iv, %end
  br i1 %cmp.not, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i1 %any.of.next
}

attributes #0 = { "target-cpu"="penryn" }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define i64 @live_in_known_1_via_scev() {
entry:
  %sel = select i1 false, i32 3, i32 0
  br label %ph

ph:                                               ; preds = %entry
  %p = phi i32 [ 1, %entry ]
  %N = add nuw nsw i32 %sel, 6
  %p.ext = zext nneg i32 %p to i64
  br label %loop

loop:                                             ; preds = %loop, %ph
  %iv = phi i32 [ 0, %ph ], [ %iv.next, %loop ]
  %red = phi i64 [ 3, %ph ], [ %red.mul, %loop ]
  %red.mul = mul nsw i64 %red, %p.ext
  %iv.next = add nuw nsw i32 %iv, 1
  %ec = icmp eq i32 %iv.next, %N
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  %res = phi i64 [ %red.mul, %loop ]
  ret i64 %res
}

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define void @reduction_store(ptr noalias %src, ptr %dst, i1 %x) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %red = phi i32 [ 0, %entry ], [ %red.next, %loop ]
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %gep.src = getelementptr inbounds i32, ptr %src, i32 %iv
  %l = load i32, ptr %gep.src, align 4
  %l.and = and i32 %l, 3
  store i32 %l.and, ptr %dst, align 4
  %x.ext = zext i1 %x to i64
  %lshr = lshr i64 %x.ext, 12
  %t = trunc i64 %lshr to i32
  %red.next = and i32 %red, %t
  store i32 %red.next, ptr %dst, align 4
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv, 29
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-cpu"="znver3" }

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

define float @PR27826(ptr nocapture readonly %a, ptr nocapture readonly %b, i32 %n) {
entry:
  %cmp = icmp sgt i32 %n, 0
  br i1 %cmp, label %preheader, label %for.end

preheader:                                        ; preds = %entry
  %t0 = sext i32 %n to i64
  br label %for

for:                                              ; preds = %for, %preheader
  %indvars.iv = phi i64 [ 0, %preheader ], [ %indvars.iv.next, %for ]
  %s.02 = phi float [ 0.000000e+00, %preheader ], [ %add4, %for ]
  %arrayidx = getelementptr inbounds float, ptr %a, i64 %indvars.iv
  %t1 = load float, ptr %arrayidx, align 4
  %arrayidx3 = getelementptr inbounds float, ptr %b, i64 %indvars.iv
  %t2 = load float, ptr %arrayidx3, align 4
  %add = fadd fast float %t1, %s.02
  %add4 = fadd fast float %add, %t2
  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 32
  %cmp1 = icmp slt i64 %indvars.iv.next, %t0
  br i1 %cmp1, label %for, label %loopexit

loopexit:                                         ; preds = %for
  %add4.lcssa = phi float [ %add4, %for ]
  br label %for.end

for.end:                                          ; preds = %loopexit, %entry
  %s.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add4.lcssa, %loopexit ]
  ret float %s.0.lcssa
}

[clang] Assertion failed in Vectorize

To reproduce, compile it with -O2: clang -O2 example.c

```c
#include <stdint.h>
int a;
long b;
static int32_t c;
void d(int e, int h) {
  int f = a = 1;
  for (; a <= e; a++)
    f *= a;
  a = 0;
  for (; a < h; a++)
    b *= f;
}
long g() {}
int32_t i() {
  for (; g();)
    for (c = 3;;)
      ;
}
uint16_t j() { d(c + 1, c + 6); }
```

The error message is as follows:

```
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:9985: bool llvm::LoopVectorizePass::processLoop(llvm::Loop *): Assertion `VF.Width == BestVF && "VPlan cost model and legacy cost model disagreed"' failed.
```

See https://godbolt.org/z/jc8qqo8Ta

Looks like a recent regression since it does not crash on trunk: https://godbolt.org/z/sKjdvMq54

Assertion:

```console
clang++: /root/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7288:
llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF():
Assertion `BestFactor.Width == LegacyVF.Width && " VPlan cost model and legacy cost model disagreed"' failed.
```

Backtrace:

```console
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -x c -O2 <source>
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "<source>"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "j"
 #0 0x0000000003b02648 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3b02648)
 #1 0x0000000003b0033c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3b0033c)
 #2 0x0000000003a492b8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x000078485ee42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000078485ee969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #5 0x000078485ee42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #6 0x000078485ee287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #7 0x000078485ee2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #8 0x000078485ee39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #9 0x00000000054df418 llvm::LoopVectorizationPlanner::computeBestVF() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x54df418)
#10 0x00000000054fa07a llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x54fa07a)
#11 0x00000000054fcd39 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x54fcd39)
#12 0x00000000054fd3c3 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x54fd3c3)
#13 0x00000000050ac09e 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/clang+++0x50ac09e)
#14 0x00000000034cac68 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x34cac68)
#15 0x00000000010bce6e 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/clang+++0x10bce6e)
#16 0x00000000034c966e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x34c966e)
#17 0x00000000010bc75e 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/clang+++0x10bc75e)
#18 0x00000000034c7800 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x34c7800)
#19 0x0000000003da8895 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#20 0x0000000003dab9fd clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3dab9fd)
#21 0x00000000044196ac clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x44196ac)
#22 0x000000000651f80c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x651f80c)
#23 0x0000000004419b18 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4419b18)
#24 0x00000000046a79f9 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x46a79f9)
#25 0x000000000462b30e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x462b30e)
#26 0x000000000479104e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x479104e)
#27 0x0000000000ca5b0f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xca5b0f)
#28 0x0000000000c9ed5a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#29 0x000000000445d1d9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#30 0x0000000003a49764 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a49764)
#31 0x000000000445d7cf clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#32 0x0000000004423365 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4423365)
#33 0x0000000004423dcd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4423dcd)
#34 0x000000000442b9e5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x442b9e5)
#35 0x0000000000ca2f05 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xca2f05)
#36 0x0000000000b776e4 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xb776e4)
#37 0x000078485ee29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#38 0x000078485ee29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#39 0x0000000000c9e80e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xc9e80e)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134
```

The crash persists in the above cases even with the applied patches.

@cardigan1008 I can't reproduce the crash locally with latest main. If it still reproduces on current main for you, could you share the crashing IR, using `-mllvm -print-on-crash -mllvm -print-module-scope`?

@fhahn Apologies for the confusion. I pulled the latest version, and this case is now working. However, I encountered a similar crash with another case that I'm currently fuzzing. I'll open a separate issue as soon as I've finished reducing it.

Hi @fhahn , I have submitted another issue with the same crash in #106248 .


commit 0a272d3a1703415abca42dc2e2cc2b57cb30734e
Author: Florian Hahn <flo@fhahn.com>
Date:   Thu Aug 29 12:08:27 2024 +0100

    [LV] Use SCEV to analyze second operand for cost query.

    Improve operand analysis using SCEV for cost purposes. This fixes a
    divergence between legacy and VPlan-based cost-modeling after
    533e6bbd0d34.

    Fixes https://github.com/llvm/llvm-project/issues/106248.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 56f51e14a6eb..4cc75e2e7546 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -6529,6 +6529,10 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I,
     // Certain instructions can be cheaper to vectorize if they have a constant
     // second vector operand. One example of this are shifts on x86.
     Value *Op2 = I->getOperand(1);
+    if (!isa<Constant>(Op2) && PSE.getSE()->isSCEVable(Op2->getType()) &&
+        isa<SCEVConstant>(PSE.getSCEV(Op2))) {
+      Op2 = cast<SCEVConstant>(PSE.getSCEV(Op2))->getValue();
+    }
     auto Op2Info = TTI.getOperandInfo(Op2);
     if (Op2Info.Kind == TargetTransformInfo::OK_AnyValue &&
         Legal->isInvariant(Op2))

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"
target triple = "x86_64-unknown-linux-gnu"

define i64 @test_foldable_live_in_via_scev() {
entry:
  %conv = zext i16 -6 to i64
  %add = add nsw i64 %conv, -65528
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ]
  %red = phi i64 [ 1, %entry ], [ %mul, %loop ]
  %mul = mul nsw i64 %red, %add
  %iv.next = add nsw i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  %ret = phi i64 [ %mul, %loop ]
  ret i64 %ret
}

[clang] Assertion failed in Vectorize

In #105722 , we resolved the assertion failure in vectorization. However, I met this crash again with the following case:

```c
#include <stdint.h>
int a;
long b;
struct e {
  uint16_t f;
  uint64_t g;
  int32_t h
} static i = {65530};
void c(int d) {
  for (; a; a++)
    b *= d;
}
uint32_t j(struct e, uint16_t);
uint64_t k() { j(i, 0); }
uint32_t j(struct e, uint16_t) { c(i.f - 65528); }
```
I compiled it with -O2 flag and it crashed. But when I compiled with -O1/-O0, it worked.

The crash is: clang++: /root/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7359: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), BestFactor.Width, CostCtx, OrigLoop, CM)) && " VPlan cost model and legacy cost model disagreed"' failed.

The details can be found here: https://godbolt.org/z/8x48xsKs6

Thanks for the report @cardigan1008, should be fixed now


commit 7aed53eb1982113e825534f0f66d0a0e46e7a5ed
Author: Nikita Popov <npopov@redhat.com>
Date:   Mon Feb 10 10:07:21 2025 +0100

    [ScalarEvolution] Handle addrec incoming value in isImpliedViaMerge() (#126236)

    The code already guards against values coming from a previous iteration
    using properlyDominates(). However, addrecs are considered to properly
    dominate the loop they are defined in.

    Handle this special case separately, by checking for expressions that
    have computable loop evolution (this should cover cases like a zext of
    an addrec as well).

    I considered changing the definition of properlyDominates() instead, but
    decided against it. The current definition is useful in other context,
    e.g. when deciding whether an expression is safe to expand in a given
    block.

    Fixes https://github.com/llvm/llvm-project/issues/126012.

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index f89887118d8d..46a5c44f4e41 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12400,6 +12400,12 @@ bool ScalarEvolution::isImpliedViaMerge(CmpPredicate Pred, const SCEV *LHS,
       // iteration of a loop.
       if (!properlyDominates(L, LBB))
         return false;
+      // Addrecs are considered to properly dominate their loop, so are missed
+      // by the previous check. Discard any values that have computable
+      // evolution in this loop.
+      if (auto *Loop = LI.getLoopFor(LBB))
+        if (hasComputableLoopEvolution(L, Loop))
+          return false;
       if (!ProvedEasily(L, RHS))
         return false;
     }

define i32 @test() {
entry:
  br label %for.preheader

for.preheader:                                    ; preds = %for.inc, %entry
  %indvar1 = phi i32 [ 0, %entry ], [ %phi, %for.inc ]
  %indvar2 = phi i32 [ 1, %entry ], [ %indvar3, %for.inc ]
  %indvar3 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
  %cond1 = icmp eq i32 %indvar3, 0
  br i1 %cond1, label %for.inc, label %for.end

for.end:                                          ; preds = %for.preheader
  %cmp = icmp sgt i32 %indvar2, 0
  %ext = zext i1 %cmp to i32
  br label %for.inc

for.inc:                                          ; preds = %for.end, %for.preheader
  %phi = phi i32 [ %ext, %for.end ], [ 0, %for.preheader ]
  %inc = add i32 %indvar3, 1
  %exitcond = icmp eq i32 %indvar3, 2
  br i1 %exitcond, label %for.exit, label %for.preheader

for.exit:                                         ; preds = %for.inc
  ret i32 %indvar1
}

[IndVarSimplify] Miscompilation at O2

Reproducer: https://alive2.llvm.org/ce/z/UTnMBe
```
; bin/opt -passes=indvars reduced.ll -S
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"
target triple = "x86_64-unknown-linux-gnu"

@.str = constant [4 x i8] c"%d\0A\00"

define i32 @main() {
entry:
  br label %for.cond1.preheader.i.i

for.cond1.preheader.i.i:                          ; preds = %for.inc18.i.i, %entry
  %.pre.i.i = phi i64 [ 0, %entry ], [ %1, %for.inc18.i.i ]
  %j.sroa.0.043.i.i = phi i64 [ 1, %entry ], [ %storemerge42.i.i, %for.inc18.i.i ]
  %storemerge42.i.i = phi i64 [ 0, %entry ], [ %inc22.i.i, %for.inc18.i.i ]
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i

for.end.i.i:                                      ; preds = %for.cond1.preheader.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0
  %dec.348.i.i = add i64 %.pre.i.i, 1
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0
  br label %for.inc18.i.i

for.inc18.i.i:                                    ; preds = %for.end.i.i, %for.cond1.preheader.i.i
  %1 = phi i64 [ %spec.select.i.i, %for.end.i.i ], [ 0, %for.cond1.preheader.i.i ]
  %inc22.i.i = add i64 %storemerge42.i.i, 1
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i

g.exit:                                           ; preds = %for.inc18.i.i
  %conv = trunc i64 %.pre.i.i to i32
  %call1 = call i32 (ptr, ...) @printf(ptr @.str, i32 %conv)
  ret i32 0
}

declare i32 @printf(ptr, ...)
```
Before:
```
Entering function main
  br label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 0
    phi i64 %j.sroa.0.043.i.i -> i64 1
    phi i64 %storemerge42.i.i -> i64 0
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> T
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 0
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 1
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 0
    phi i64 %j.sroa.0.043.i.i -> i64 0
    phi i64 %storemerge42.i.i -> i64 1
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> F
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 1
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 0
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 0
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 2
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 0
    phi i64 %j.sroa.0.043.i.i -> i64 1
    phi i64 %storemerge42.i.i -> i64 2
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 1
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 1
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 1
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 3
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 1
    phi i64 %j.sroa.0.043.i.i -> i64 2
    phi i64 %storemerge42.i.i -> i64 3
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 2
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 2
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 2
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 4
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 2
    phi i64 %j.sroa.0.043.i.i -> i64 3
    phi i64 %storemerge42.i.i -> i64 4
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 3
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 3
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 3
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 5
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 3
    phi i64 %j.sroa.0.043.i.i -> i64 4
    phi i64 %storemerge42.i.i -> i64 5
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 4
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 4
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 4
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 6
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 4
    phi i64 %j.sroa.0.043.i.i -> i64 5
    phi i64 %storemerge42.i.i -> i64 6
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 5
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 5
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 5
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 7
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 5
    phi i64 %j.sroa.0.043.i.i -> i64 6
    phi i64 %storemerge42.i.i -> i64 7
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 6
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 6
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 6
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 8
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 6
    phi i64 %j.sroa.0.043.i.i -> i64 7
    phi i64 %storemerge42.i.i -> i64 8
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 7
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 7
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 7
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 9
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 7
    phi i64 %j.sroa.0.043.i.i -> i64 8
    phi i64 %storemerge42.i.i -> i64 9
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %0 = icmp sgt i64 %j.sroa.0.043.i.i, 0 -> T
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 8
  %spec.select.i.i = select i1 %0, i64 %dec.348.i.i, i64 0 -> i64 8
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %1 -> i64 8
  %inc22.i.i = add i64 %storemerge42.i.i, 1 -> i64 10
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> T
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %g.exit
  %conv = trunc i64 %.pre.i.i to i32 -> i32 7
  %call1 = call i32 (ptr, ...) @printf(ptr @.str, i32 %conv)
    Printf: 7
   -> i32 2
  ret i32 0
Exiting function main
```
After:
```
; 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"
target triple = "x86_64-unknown-linux-gnu"

@.str = constant [4 x i8] c"%d\0A\00"

define i32 @main() {
entry:
  br label %for.cond1.preheader.i.i

for.cond1.preheader.i.i:                          ; preds = %for.inc18.i.i, %entry
  %.pre.i.i = phi i64 [ 0, %entry ], [ %0, %for.inc18.i.i ]
  %storemerge42.i.i = phi i64 [ 0, %entry ], [ %inc22.i.i, %for.inc18.i.i ]
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i

for.end.i.i:                                      ; preds = %for.cond1.preheader.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0
  br label %for.inc18.i.i

for.inc18.i.i:                                    ; preds = %for.end.i.i, %for.cond1.preheader.i.i
  %0 = phi i64 [ %spec.select.i.i, %for.end.i.i ], [ 0, %for.cond1.preheader.i.i ]
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i

g.exit:                                           ; preds = %for.inc18.i.i
  %.pre.i.i.lcssa = phi i64 [ %.pre.i.i, %for.inc18.i.i ]
  %conv = trunc i64 %.pre.i.i.lcssa to i32
  %call1 = call i32 (ptr, ...) @printf(ptr @.str, i32 %conv)
  ret i32 0
}

declare i32 @printf(ptr, ...)
```
```
Entering function main
  br label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 0
    phi i64 %storemerge42.i.i -> i64 0
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> T
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 0
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 1
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 0
    phi i64 %storemerge42.i.i -> i64 1
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 1
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 1
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 1
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 2
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 1
    phi i64 %storemerge42.i.i -> i64 2
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 2
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 2
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 2
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 3
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 2
    phi i64 %storemerge42.i.i -> i64 3
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 3
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 3
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 3
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 4
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 3
    phi i64 %storemerge42.i.i -> i64 4
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 4
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 4
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 4
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 5
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 4
    phi i64 %storemerge42.i.i -> i64 5
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 5
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 5
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 5
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 6
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 5
    phi i64 %storemerge42.i.i -> i64 6
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 6
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 6
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 6
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 7
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 6
    phi i64 %storemerge42.i.i -> i64 7
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 7
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 7
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 7
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 8
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 7
    phi i64 %storemerge42.i.i -> i64 8
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 8
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 8
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 8
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 9
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> F
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %for.cond1.preheader.i.i
    phi i64 %.pre.i.i -> i64 8
    phi i64 %storemerge42.i.i -> i64 9
  %tobool.not.i.i = icmp eq i64 %storemerge42.i.i, 0 -> F
  br i1 %tobool.not.i.i, label %for.inc18.i.i, label %for.end.i.i jump to %for.end.i.i
  %dec.348.i.i = add i64 %.pre.i.i, 1 -> i64 9
  %spec.select.i.i = select i1 true, i64 %dec.348.i.i, i64 0 -> i64 9
  br label %for.inc18.i.i jump to %for.inc18.i.i
    phi i64 %0 -> i64 9
  %inc22.i.i = add nuw nsw i64 %storemerge42.i.i, 1 -> i64 10
  %exitcond50.not.i.i = icmp eq i64 %storemerge42.i.i, 9 -> T
  br i1 %exitcond50.not.i.i, label %g.exit, label %for.cond1.preheader.i.i jump to %g.exit
    phi i64 %.pre.i.i.lcssa -> i64 8
  %conv = trunc i64 %.pre.i.i.lcssa to i32 -> i32 8
  %call1 = call i32 (ptr, ...) @printf(ptr @.str, i32 %conv)
    Printf: 8
   -> i32 2
  ret i32 0
Exiting function main
```
llvm version: 52fc6ffcda0895c0c7b976ad1f5cb5a282b571d2

Reduced reproducer: https://alive2.llvm.org/ce/z/_x96gs
```
; bin/opt -passes=indvars reduced.ll -S --debug
define i32 @src() {
entry:
  br label %for.preheader

for.preheader:
  %indvar1 = phi i32 [ 0, %entry ], [ %phi, %for.inc ]
  %indvar2 = phi i32 [ 1, %entry ], [ %indvar3, %for.inc ]
  %indvar3 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
  %cond1 = icmp eq i32 %indvar3, 0
  br i1 %cond1, label %for.inc, label %for.end

for.end:
  %cmp = icmp sgt i32 %indvar2, 0
  %ext = zext i1 %cmp to i32
  br label %for.inc

for.inc:
  %phi = phi i32 [ %ext, %for.end ], [ 0, %for.preheader ]
  %inc = add i32 %indvar3, 1
  %exitcond = icmp eq i32 %indvar3, 2
  br i1 %exitcond, label %for.exit, label %for.preheader

for.exit:
  ret i32 %indvar1
}

```
```
INDVARS: Eliminated comparison:   %cmp = icmp sgt i32 %indvar2, 0

define i32 @src() {
entry:
  br label %for.preheader

for.preheader:                                    ; preds = %for.inc, %entry
  %indvar1 = phi i32 [ 0, %entry ], [ %phi, %for.inc ]
  %indvar3 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
  %cond1 = icmp eq i32 %indvar3, 0
  br i1 %cond1, label %for.inc, label %for.end

for.end:                                          ; preds = %for.preheader
  %ext = zext i1 true to i32
  br label %for.inc

for.inc:                                          ; preds = %for.end, %for.preheader
  %phi = phi i32 [ %ext, %for.end ], [ 0, %for.preheader ]
  %inc = add nuw nsw i32 %indvar3, 1
  %exitcond = icmp eq i32 %indvar3, 2
  br i1 %exitcond, label %for.exit, label %for.preheader

for.exit:                                         ; preds = %for.inc
  %indvar1.lcssa = phi i32 [ %indvar1, %for.inc ]
  ret i32 %indvar1.lcssa
}
```
`ScalarEvolution::isImpliedViaMerge(sgt, %indvar2, 0, {0,+,1}<nuw><nsw><%for.preheader>(= %indvar3), 0)` wrongly returns true.
I can't quite understand why `%indvar3` properly dominates `%for.preheader`: https://github.com/llvm/llvm-project/blob/26ecddb05d13c101ccd840a6710eb5f8b82de841/llvm/lib/Analysis/ScalarEvolution.cpp#L14131-L14141

@nikic @fhahn Can you help fix this issue?

Related previous fix: https://reviews.llvm.org/D101829