Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp: planContainsAdditionalSimplifications
Issue title: [VPlan] Assertion " VPlan cost model and legacy cost model disagreed"' failed.
Labels: vectorizers
crash
Reported by: patrick-rivos

Testing using 0c1500ef05e0a5b25cae79d2bd361dbc6e14e726

C testcase:
```
int a;
extern int b[][3][3][3][3][3];
_Bool c;
unsigned char d[1][13][13];
unsigned e[1][13][13][13];
int f[6];
unsigned short g[1][13][13][13];
unsigned h[1][13][13], i[1][13][13];
short j[1][13][13];
unsigned k[3][13][13];
unsigned short l[1][13];
short m[1][13];
unsigned short n[1][13][13];
unsigned o[1][13];
void p(char q, int r, char s, unsigned char z[][13][13],
       unsigned aa[][13][13][13], int ab[], unsigned short ac[][13][13][13],
       unsigned ad[][13][13], short ae[][13][13], unsigned af[][13][13],
       unsigned short ag[][13], short ah[][13], unsigned short ai[][13][13],
       unsigned aj[][13][13], unsigned ak[][13]) {
  for (unsigned t = 0; t < q; t += 50)
    for (unsigned u = 0; u < 2; u = 6)
      for (short w = 0; w < 2; w += 42155)
        for (signed x = -15; x < r; x += s) {
          b[x][x][u][2][x][2] = ab[5] ? ~af[2][1][x] : 0;
          a = x ? c ? aj[2][u][x] : 0 : ae[2][w][4];
        }
}
int main() {
  f[5] = 8;
  for (long t = 0; t < 3; ++t)
    for (long v = 0; v < 3; ++v)
      for (long y = 0; y < 3; ++y)
        k[t][v][y] = 3004284279;
  p(8, 322, 9, d, e, f, g, h, j, k, l, m, n, i, o);
}
```

LLVM IR:
```llvm ir
; ModuleID = 'reduced.bc'
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define i32 @main(i64 %indvars.iv) #0 {
entry:
  br label %for.body17.us77.us.us.i

for.body17.us77.us.us.i:                          ; preds = %cond.end.us84.us.us.i, %entry
  %indvars.iv1 = phi i64 [ %indvars.iv.next, %cond.end.us84.us.us.i ], [ 0, %entry ]
  br i1 false, label %cond.end.us84.us.us.i, label %cond.true.us80.us.us.i

cond.true.us80.us.us.i:                           ; preds = %for.body17.us77.us.us.i
  %not.us83.us.us.i = xor i32 0, 0
  br label %cond.end.us84.us.us.i

cond.end.us84.us.us.i:                            ; preds = %cond.true.us80.us.us.i, %for.body17.us77.us.us.i
  %cond.us85.us.us.i = phi i32 [ %not.us83.us.us.i, %cond.true.us80.us.us.i ], [ 0, %for.body17.us77.us.us.i ]
  %arrayidx30.us87.us.us.i = getelementptr [0 x [3 x [3 x [3 x [3 x [3 x i32]]]]]], ptr null, i64 0, i64 %indvars.iv1, i64 %indvars.iv, i64 0, i64 2, i64 %indvars.iv, i64 2
  store i32 %cond.us85.us.us.i, ptr %arrayidx30.us87.us.us.i, align 4
  %indvars.iv.next = add i64 %indvars.iv1, 9
  %cmp14.us95.us.us.i = icmp slt i64 %indvars.iv1, 322
  br i1 %cmp14.us95.us.us.i, label %for.body17.us77.us.us.i, label %for.body17.us77.us.us.1.i.preheader

for.body17.us77.us.us.1.i.preheader:              ; preds = %cond.end.us84.us.us.i
  ret i32 0
}

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-b,-e,-experimental-smctr,-experimental-smmpm,-experimental-smnpm,-experimental-ssctr,-experimental-ssnpm,-experimental-sspm,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
```

Command/backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=loop-vectorize reduced.ll -S
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7400: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=loop-vectorize reduced.ll -S
1.      Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "reduced.ll"
2.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x000059162be7f6e0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x30136e0)
 #1 0x000059162be7caef llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x3010aef)
 #2 0x000059162be7cc45 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007152dd642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007152dd6969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007152dd6969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007152dd6969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007152dd642476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007152dd6287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007152dd62871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007152dd639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000059162ae52310 llvm::LoopVectorizationPlanner::computeBestVF() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1fe6310)
#12 0x000059162ae6910b llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1ffd10b)
#13 0x000059162ae6c121 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2000121)
#14 0x000059162ae6c797 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2000797)
#15 0x0000591629cc8756 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5c756)
#16 0x000059162bc8b67f llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1f67f)
#17 0x0000591629ccb8e6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5f8e6)
#18 0x000059162bc89a1b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1da1b)
#19 0x0000591629cc7b36 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5bb36)
#20 0x000059162bc8a57d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1e57d)
#21 0x00005916294f41b6 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) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6881b6)
#22 0x00005916294e5f11 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x679f11)
#23 0x00007152dd629d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#24 0x00007152dd629e40 call_init ./csu/../csu/libc-start.c:128:20
#25 0x00007152dd629e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#26 0x00005916294dc2c5 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6702c5)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```
https://godbolt.org/z/qEEqe1exM

Found via fuzzer

Related/prior issue: https://github.com/llvm/llvm-project/issues/107171

cc @fhahn

Comments: author: patrick-rivos
body: Ping. The C fuzzer is hitting this assertion ~15 times a day since the runs starting sep 6th.

Fix patch:
commit e3c537ff903af9a92ff43bab6d21c0ea759d65e5
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Sep 10 21:37:12 2024 +0100

    [VPlan] Consider non-header phis in planContainsAdditionalSimp.
    
    Update planContainsAdditionalSimplifications to also check phis not in
    the loop header. This ensures we don't miss cases where VPBlendRecipes
    (which correspond to such phis) have been simplified.
    
    Fixes https://github.com/llvm/llvm-project/issues/107473.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 2be3b5775292..b821da03c16e 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7314,9 +7314,10 @@ static bool planContainsAdditionalSimplifications(VPlan &Plan,
   // Return true if the loop contains any instructions that are not also part of
   // the VPlan or are skipped for VPlan-based cost computations. This indicates
   // that the VPlan contains extra simplifications.
-  return any_of(TheLoop->blocks(), [&SeenInstrs, &CostCtx](BasicBlock *BB) {
-    return any_of(*BB, [&SeenInstrs, &CostCtx](Instruction &I) {
-      if (isa<PHINode>(&I))
+  return any_of(TheLoop->blocks(), [&SeenInstrs, &CostCtx,
+                                    TheLoop](BasicBlock *BB) {
+    return any_of(*BB, [&SeenInstrs, &CostCtx, TheLoop, BB](Instruction &I) {
+      if (isa<PHINode>(&I) && BB == TheLoop->getHeader())
         return false;
       return !SeenInstrs.contains(&I) && !CostCtx.skipCostComputation(&I, true);
     });


Regression tests:
file: llvm/test/Transforms/LoopVectorize/RISCV/dead-ops-cost.ll
commands: opt -p loop-vectorize -mtriple riscv64-linux-gnu -mattr=+v,+f -S %s
tests: test_name: dead_load
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define void @dead_load(ptr %p, i16 %start) {
entry:
  %start.ext = sext i16 %start to i64
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ %start.ext, %entry ], [ %iv.next, %loop ]
  %gep = getelementptr i16, ptr %p, i64 %iv
  store i16 0, ptr %gep, align 2
  %l = load i16, ptr %gep, align 2
  %iv.next = add i64 %iv, 3
  %cmp = icmp slt i64 %iv, 111
  br i1 %cmp, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

test_name: dead_live_out_due_to_scalar_epilogue_required
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define i8 @dead_live_out_due_to_scalar_epilogue_required(ptr %src, ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %idxprom = sext i32 %iv to i64
  %gep.src = getelementptr i8, ptr %src, i64 %idxprom
  %l = load i8, ptr %gep.src, align 1
  %gep.dst = getelementptr i8, ptr %dst, i64 %idxprom
  store i8 0, ptr %gep.dst, align 1
  %iv.next = add i32 %iv, 4
  %cmp = icmp ult i32 %iv, 1001
  br i1 %cmp, label %loop, label %exit

exit:                                             ; preds = %loop
  %r = phi i8 [ %l, %loop ]
  ret i8 %r
}

test_name: test_phi_in_latch_redundant
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define void @test_phi_in_latch_redundant(ptr %dst, i32 %a) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  br i1 false, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  %not.a = xor i32 %a, -1
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %p = phi i32 [ %not.a, %then ], [ 0, %loop.header ]
  %gep = getelementptr i32, ptr %dst, i64 %iv
  store i32 %p, ptr %gep, align 4
  %iv.next = add i64 %iv, 9
  %ec = icmp slt i64 %iv, 322
  br i1 %ec, label %loop.header, label %exit

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

test_name: cost_of_exit_branch_and_cond_insts
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

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

define i32 @cost_of_exit_branch_and_cond_insts(ptr %a, ptr %b, i1 %c, i16 %x) {
entry:
  br label %loop.header

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

then:                                             ; preds = %loop.header
  %gep = getelementptr inbounds i32, ptr %b, i32 %iv
  store i1 false, ptr %a, align 1
  store i32 0, ptr %gep, align 4
  br label %loop.exiting

loop.exiting:                                     ; preds = %then, %loop.header
  %iv.next = add i32 %iv, 1
  %umax = tail call i16 @llvm.umax.i16(i16 %x, i16 111)
  %umax.ext = zext i16 %umax to i32
  %sub = sub i32 770, %umax.ext
  %ec = icmp slt i32 %iv, %sub
  br i1 %ec, label %loop.latch, label %exit

loop.latch:                                       ; preds = %loop.exiting
  br label %loop.header

exit:                                             ; preds = %loop.exiting
  br label %return

return:                                           ; preds = %exit
  ret i32 0
}

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