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

Testcase:
```c
extern char a[];
char *b;
int c = 40502824327348188;
long d[9][9];
int main() {
  for (long e = 0; e < 9; ++e)
    for (long f = 0; f < 9; ++f)
      d[e][f] = 6032102684657866;
  for (unsigned char f = b[4]; f < 18; f += c - 216)
    a[f] = f % 2 ? d[f][f] : d[f][f] + 2036854775807 > 0;
}
```
```
/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/clang -I/scratch/tc-testing/compiler-fuzz-ci/csmith-build/include -fsigned-char -fno-strict-aliasing -fwrapv -march=rv64gcv -flto -O3 -fuse-ld=lld red.c -o rv64gcv.out
```


Reduced testcase:
```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() #0 {
entry:
  br label %for.body15

for.cond.cleanup14.loopexit:                      ; preds = %for.body15
  ret i32 0

for.body15:                                       ; preds = %for.body15, %entry
  %indvars.iv1 = phi i64 [ %indvars.iv.next, %for.body15 ], [ 0, %entry ]
  %tobool.not = icmp eq i8 0, 0
  %cmp24 = icmp sgt i64 %indvars.iv1, 0
  %conv26 = zext i1 %cmp24 to i64
  %cond = select i1 %tobool.not, i64 %conv26, i64 0
  %conv27 = trunc i64 %cond to i8
  store i8 %conv27, ptr null, align 1
  %indvars.iv.next = add i64 %indvars.iv1, 4
  %cmp12 = icmp ult i64 %indvars.iv1, 14
  br i1 %cmp12, label %for.body15, label %for.cond.cleanup14.loopexit
}

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-ssctr,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-h,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-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,-zacas,-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 -f
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7519: 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 -f
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 0x00005f3d9fc9dc00 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x3169c00)
 #1 0x00005f3d9fc9b00f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x316700f)
 #2 0x00005f3d9fc9b165 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007abb28242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007abb282969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007abb282969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007abb282969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007abb28242476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007abb282287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007abb2822871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007abb28239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00005f3d9ebfb878 llvm::LoopVectorizationPlanner::computeBestVF() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20c7878)
#12 0x00005f3d9ec12dec llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20dedec)
#13 0x00005f3d9ec15f01 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20e1f01)
#14 0x00005f3d9ec16577 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20e2577)
#15 0x00005f3d9da0cba6 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+0xed8ba6)
#16 0x00005f3d9faa518f 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+0x2f7118f)
#17 0x00005f3d9da0fdd6 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+0xedbdd6)
#18 0x00005f3d9faa351b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f6f51b)
#19 0x00005f3d9da0bc66 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+0xed7c66)
#20 0x00005f3d9faa407d 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+0x2f7007d)
#21 0x00005f3d9d20ca8d 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+0x6d8a8d)
#22 0x00005f3d9d1fe911 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6ca911)
#23 0x00007abb28229d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#24 0x00007abb28229e40 call_init ./csu/../csu/libc-start.c:128:20
#25 0x00007abb28229e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#26 0x00005f3d9d1f4e65 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6c0e65)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Found via fuzzer on Oct 24th

Godbolt: https://godbolt.org/z/zhseEjTso

cc @fhahn 


Fix patch:
commit 144bdf3eb7128518ed162c5a168e3ec90922cd9e
Author: Florian Hahn <flo@fhahn.com>
Date:   Fri Nov 8 20:53:03 2024 +0000

    [VPlan] Also check if plan for best legacy VF contains simplifications.
    
    The plan for the VF chosen by the legacy cost model could also contain
    additional simplifications that cause cost differences. Also check if it
    contains simplifications.
    
    Fixes https://github.com/llvm/llvm-project/issues/114860.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index c07af8519049..82d85b112397 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7521,6 +7521,8 @@ VectorizationFactor LoopVectorizationPlanner::computeBestVF() {
   precomputeCosts(BestPlan, BestFactor.Width, CostCtx);
   assert((BestFactor.Width == LegacyVF.Width ||
           planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width),
+                                                CostCtx, OrigLoop) ||
+          planContainsAdditionalSimplifications(getPlanFor(LegacyVF.Width),
                                                 CostCtx, OrigLoop)) &&
          " VPlan cost model and legacy cost model disagreed");
   assert((BestFactor.Width.isScalar() || BestFactor.ScalarCost > 0) &&


Regression tests:
file: llvm/test/Transforms/LoopVectorize/RISCV/select-invariant-cond-cost.ll
commands: opt -p loop-vectorize -S %s
tests: test_name: test_invariant_cond_for_select
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @test_invariant_cond_for_select(ptr %dst, i8 %x) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %c.1 = icmp eq i8 %x, 0
  %c.2 = icmp sgt i64 %iv, 0
  %c.2.ext = zext i1 %c.2 to i64
  %sel = select i1 %c.1, i64 %c.2.ext, i64 0
  %sel.trunc = trunc i64 %sel to i8
  %gep = getelementptr inbounds i8, ptr %dst, i64 %iv
  store i8 %sel.trunc, ptr %gep, align 1
  %iv.next = add i64 %iv, 4
  %ec = icmp ult i64 %iv, 14
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-features"="+64bit,+v" }