Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp: VPlanTransforms::optimize
Issue title: A/F: verifyVPlanIsValid(*Plan) && "VPlan is invalid" after a861ed411a
Labels: vectorizers
crash
Reported by: dyung

We have an internal test that recently started to hit an assertion failure which I bisected back to commit a861ed411a359b7cb2b58d642e4a7f2fdcf92057. 

Consider the following code:
```c
int g_78, g_659, func_32_l_1852;
long g_128;
unsigned func_32_p_33;
void func_32() {
  int *l_1145 = &g_659;
  *l_1145 = 0;
  short __trans_tmp_11;
  for (; g_78; g_78 += 1) {
    func_32_l_1852 = 0;
    for (; func_32_l_1852 <= 3; func_32_l_1852 += 1) {
      int *l_1863 = &g_659;
      __trans_tmp_11 = *l_1863;
      if (10 % ((__trans_tmp_11 >= 0) - func_32_p_33))
        break;
      ++g_128;
      *l_1863 = func_32_p_33 <= --g_128;
    }
  }
}
```

If compiled with optimizations and a compiler built from a861ed411a359b7cb2b58d642e4a7f2fdcf92057 you can see it hits an assertion failure:
```
$ ~/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang -c -O2 repro.c
VPIRBasicBlock can only be used as pre-header or a successor of middle-block at the moment!
clang: /home/dyung/src/upstream/llvm_clean_git/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8594: void llvm::LoopVectorizationPlanner::buildVPlansWithVPRecipes(llvm::ElementCount, llvm::ElementCount): Assertion `verifyVPlanIsValid(*Plan) && "VPlan is invalid"' failed.
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: /home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang -c -O2 repro.c
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-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;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;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "repro.c"
4.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "func_32"
 #0 0x00005572973a049f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x233549f)
 #1 0x000055729739dfec llvm::sys::CleanupOnSignal(unsigned long) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2332fec)
 #2 0x00005572972f0418 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007f5d2a347420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007f5d29e1400b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #5 0x00007f5d29df3859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #6 0x00007f5d29df3729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #7 0x00007f5d29df3729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #8 0x00007f5d29e04fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #9 0x0000557298e08438 llvm::LoopVectorizationPlanner::buildVPlansWithVPRecipes(llvm::ElementCount, llvm::ElementCount) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x3d9d438)
#10 0x0000557298e0878f llvm::LoopVectorizationPlanner::plan(llvm::ElementCount, unsigned int) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x3d9d78f)
#11 0x0000557298e0a62e llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x3d9f62e)
#12 0x0000557298e0d501 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x3da2501)
#13 0x0000557298e0db73 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x3da2b73)
#14 0x0000557298836146 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x37cb146)
#15 0x0000557296e5bd41 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x1df0d41)
#16 0x0000557295f84cc6 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/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0xf19cc6)
#17 0x0000557296e5a6ad llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x1def6ad)
#18 0x0000557295f85686 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0xf1a686)
#19 0x0000557296e5a0e1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x1def0e1)
#20 0x0000557297636863 (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
#21 0x0000557297639dbd 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*) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x25cedbd)
#22 0x0000557297d17c5c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2cacc5c)
#23 0x0000557299c7aa8c clang::ParseAST(clang::Sema&, bool, bool) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x4c0fa8c)
#24 0x0000557297d18078 clang::CodeGenAction::ExecuteAction() (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2cad078)
#25 0x0000557297fdf129 clang::FrontendAction::Execute() (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2f74129)
#26 0x0000557297f5b6fe clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2ef06fe)
#27 0x00005572980cba26 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x3060a26)
#28 0x0000557295f09185 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0xe9e185)
#29 0x0000557295f00f0a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#30 0x0000557297d5e0cd 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
#31 0x00005572972f0920 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2285920)
#32 0x0000557297d5e6ef 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
#33 0x0000557297d22274 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2cb7274)
#34 0x0000557297d2338d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2cb838d)
#35 0x0000557297d2b4a5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0x2cc04a5)
#36 0x0000557295f0611b clang_main(int, char**, llvm::ToolContext const&) (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0xe9b11b)
#37 0x0000557295e3609b main (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0xdcb09b)
#38 0x00007f5d29df5083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#39 0x0000557295f0099e _start (/home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin/clang+0xe9599e)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 20.0.0 (https://github.com/llvm/llvm-project.git a861ed411a359b7cb2b58d642e4a7f2fdcf92057)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/dyung/src/upstream/a861ed411a359b7cb2b58d642e4a7f2fdcf92057-linux/bin
Build config: +assertions
```

Building with a compiler built from the commit that immediately preceded this one (37e5319a12ba47c18049728804d3d1e1b10c4eb4), you can see that the compilation succeeds.
```
$ ~/src/upstream/37e5319a12ba47c18049728804d3d1e1b10c4eb4-linux/bin/clang -c -O2 repro.c
$
```


Fix patch:
commit bd8fe9972e3f17776e4e05e69e13ab8271d34132
Author: Florian Hahn <flo@fhahn.com>
Date:   Sat Sep 21 12:45:36 2024 +0100

    [VPlan] Mov licm to end of VPlan optimizations.
    
    This moves licm after expanding replicate regions. This fixes a crash
    when trying to hoist a predicated VPReplicateRecipes which later get
    expanded to replicate regions.
    
    Hoisting replicate regions out was not intended (see the discussion and
    at the review and comment on shallow traversal in licm()).
    
    Fixes https://github.com/llvm/llvm-project/issues/109510.

diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 06ac15f52fe1..fd6090affbbf 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1158,7 +1158,6 @@ void VPlanTransforms::optimize(VPlan &Plan) {
   removeRedundantInductionCasts(Plan);
 
   simplifyRecipes(Plan);
-  licm(Plan);
   legalizeAndOptimizeInductions(Plan);
   removeDeadRecipes(Plan);
 
@@ -1166,6 +1165,7 @@ void VPlanTransforms::optimize(VPlan &Plan) {
 
   removeRedundantExpandSCEVRecipes(Plan);
   mergeBlocksIntoPredecessors(Plan);
+  licm(Plan);
 }
 
 // Add a VPActiveLaneMaskPHIRecipe and related recipes to \p Plan and replace


Regression tests:
file: llvm/test/Transforms/LoopVectorize/invariant-replicate-region.ll
commands: opt -p loop-vectorize -force-vector-width=4 -S %s
tests: test_name: test_invariant_replicate_region
test_body: target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "arm64-apple-macosx14.0.0"

define i32 @test_invariant_replicate_region(i32 %x, i1 %c) {
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.latch

then:                                             ; preds = %loop.header
  %rem.1 = urem i32 10, %x
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %res = phi i32 [ 0, %loop.header ], [ %rem.1, %then ]
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv, 99
  br i1 %ec, label %exit, label %loop.header

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