Bug type: crash
Component: MemCpyOptimizer
Bug location: llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp: MemCpyOptPass::processMemCpyMemCpyDependence
Issue title: [MemCpyOpt] Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
Labels: crash-on-valid
llvm:transforms
Reported by: dtcxzyw

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 



Comments: author: DianQK
body: 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

Fix patch:
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);


Regression tests:
file: llvm/test/Transforms/MemCpyOpt/memcpy-memcpy-offset.ll
commands: opt < %s -passes=memcpyopt -S -verify-memoryssa
tests: test_name: do_not_forward_offset_and_store
test_body: 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) }

test_name: pr98675
test_body: @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) }