Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp: tryToFoldLiveIns
Issue title: [LoopVectorize] Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
Labels: vectorizers
crash-on-valid
generated by fuzzer
Reported by: dtcxzyw

Reproducer:
```
; bin/opt -passes=loop-vectorize 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"

define void @main(ptr %p, i1 %cmp.i.i.i.i, i64 %0) {
entry:
  br label %for.cond28.preheader.i.i.i

for.cond28.preheader.i.i.i:                       ; preds = %safe_mod_func_int64_t_s_s.exit.i.i.i, %entry
  %storemerge102.i.i.i = phi i64 [ 0, %entry ], [ %dec.i.i.i, %safe_mod_func_int64_t_s_s.exit.i.i.i ]
  br i1 %cmp.i.i.i.i, label %safe_mod_func_int64_t_s_s.exit.i.i.i, label %cond.false.i.i.i.i

cond.false.i.i.i.i:                               ; preds = %for.cond28.preheader.i.i.i
  %rem.i.i.i.i = srem i64 0, %0
  br label %safe_mod_func_int64_t_s_s.exit.i.i.i

safe_mod_func_int64_t_s_s.exit.i.i.i:             ; preds = %cond.false.i.i.i.i, %for.cond28.preheader.i.i.i
  %cond.i.i.i.i = phi i64 [ %rem.i.i.i.i, %cond.false.i.i.i.i ], [ 0, %for.cond28.preheader.i.i.i ]
  %cond.i.i.tr.i.i = trunc i64 %cond.i.i.i.i to i32
  %conv82.i.i.i = shl i32 %cond.i.i.tr.i.i, 0
  store i32 %conv82.i.i.i, ptr %p, align 4
  %dec.i.i.i = add i64 %storemerge102.i.i.i, 1
  %cmp19.not.i.i.i = icmp eq i64 %storemerge102.i.i.i, 1
  br i1 %cmp19.not.i.i.i, label %func_131.exit, label %for.cond28.preheader.i.i.i

func_131.exit:                                    ; preds = %safe_mod_func_int64_t_s_s.exit.i.i.i
  ret void
}
```
```
opt: /home/dtcxzyw/WorkSpace/Projects/compilers/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = VectorType; From = Type]: 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=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 0x0000787321a2ebb2 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.22.0git+0x22ebb2)
 #1 0x0000787321a2b17f llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.22.0git+0x22b17f)
 #2 0x0000787321a2b2cc SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x0000787321445330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
 #4 0x000078732149eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x000078732149eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x000078732149eb2c pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x000078732144527e raise ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007873214288ff abort ./stdlib/abort.c:81:7
 #9 0x000078732142881b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x000078732143b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#11 0x00007873186e3e2f simplifyExtractElementInst(llvm::Value*, llvm::Value*, llvm::SimplifyQuery const&, unsigned int) (.constprop.0) InstructionSimplify.cpp:0:0
#12 0x000078731ab13f08 tryToFoldLiveIns(llvm::VPRecipeBase const&, unsigned int, llvm::ArrayRef<llvm::VPValue*>, llvm::DataLayout const&, llvm::VPTypeAnalysis&) VPlanTransforms.cpp:0:0
#13 0x000078731ab1f860 simplifyRecipe(llvm::VPRecipeBase&, llvm::VPTypeAnalysis&) VPlanTransforms.cpp:0:0
#14 0x000078731ab22200 llvm::VPlanTransforms::simplifyRecipes(llvm::VPlan&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.22.0git+0x322200)
#15 0x000078731a8f77b6 llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, bool) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.22.0git+0xf77b6)
#16 0x000078731a90864e llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.22.0git+0x10864e)
#17 0x000078731a90ade1 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.22.0git+0x10ade1)
#18 0x000078731a90b4a6 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMVectorize.so.22.0git+0x10b4a6)
#19 0x000078731b4f0715 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMPasses.so.22.0git+0xf0715)
#20 0x0000787318122289 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.22.0git+0x322289)
#21 0x00007873204dd6b5 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.22.0git+0xdd6b5)
#22 0x00007873181227a2 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.22.0git+0x3227a2)
#23 0x0000787321d0e585 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/libLLVMOptDriver.so.22.0git+0x20585)
#24 0x0000787318123acd 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.22.0git+0x323acd)
#25 0x0000787321d1b86e 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, bool) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.22.0git+0x2d86e)
#26 0x0000787321d26a6a optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.22.0git+0x38a6a)
#27 0x000078732142a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#28 0x000078732142a28b call_init ./csu/../csu/libc-start.c:128:20
#29 0x000078732142a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#30 0x00005f2bde346095 _start (bin/opt+0x1095)
Aborted (core dumped)
```
cc @fhahn 
llvm version: 97d5d483ecc67d0b786a53d065b7202908cb4047

Comments: author: lukel97
body: I've bisected this back to 351d398a37d8545d8722ba36ad364067e94a69df, but I think it's because we can't actually fold `Instruction::ExtractElement`/`Instruction::InsertElement`/other instructions that have mixed vector + scalar types. We may have just been missing test coverage up to that commit. Will post a fix soon.

Fix patch:
commit 144736b07e03f27888860f6ad7aa13a77f7c9731
Author: Luke Lau <luke@igalia.com>
Date:   Tue Aug 19 12:10:53 2025 +0800

    [VPlan] Don't fold live ins with both scalar and vector operands (#154067)
    
    If we end up with a extract_element VPInstruction where both operands
    are live-ins, we will try to fold the live-ins even though the first
    operand is a vector whilst the live-in is scalar.
    
    This fixes it by just returning the vector live-in instead of calling
    the folder, and removes the handling for insertelement where we aren't
    able to do the fold. From some quick testing we previously never hit
    this fold anyway, and were probably just missing test coverage.
    
    Fixes #154045

diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 81088c9a8139..45d9ee1753c3 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -980,10 +980,11 @@ static Value *tryToFoldLiveIns(const VPRecipeBase &R, unsigned Opcode,
     return Folder.FoldGEP(IntegerType::getInt8Ty(TypeInfo.getContext()), Ops[0],
                           Ops[1],
                           cast<VPRecipeWithIRFlags>(R).getGEPNoWrapFlags());
-  case Instruction::InsertElement:
-    return Folder.FoldInsertElement(Ops[0], Ops[1], Ops[2]);
+  // An extract of a live-in is an extract of a broadcast, so return the
+  // broadcasted element.
   case Instruction::ExtractElement:
-    return Folder.FoldExtractElement(Ops[0], Ops[1]);
+    assert(!Ops[0]->getType()->isVectorTy() && "Live-ins should be scalar");
+    return Ops[0];
   }
   return nullptr;
 }


Regression tests:
file: llvm/test/Transforms/LoopVectorize/pr154045-dont-fold-extractelement-livein.ll
commands: opt -p loop-vectorize -force-vector-width=2 -force-widen-divrem-via-safe-divisor=false -S %s
tests: test_name: <module>
test_body: 
; Make sure we don't try to fold a Instruction::ExtractElement ir<0>, ir<0>,
; since we can't materialize the live-in for the vector operand.

define void @pr154045(ptr %p, i1 %c, i64 %x) {
;
entry:
  br label %loop

loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
  br i1 %c, label %latch, label %else

else:
  %rem = srem i64 0, %x
  br label %latch

latch:
  %phi = phi i64 [ %rem, %else ], [ 0, %loop ]
  %phi.trunc = trunc i64 %phi to i32
  %shl = shl i32 %phi.trunc, 0
  store i32 %shl, ptr %p
  %iv.next = add i64 %iv, 1
  %exitcond = icmp eq i64 %iv, 1
  br i1 %exitcond, label %exit, label %loop

exit:
  ret void
}