Bug type: hang
Component: MemCpyOptimizer
Bug location: llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp: MemCpyOptPass::processMemCpy
MemCpyOptPass::processMemSetMemCpyDependence
Issue title: Clang hangs forever building under -O1
Labels: confirmed
llvm:hang
llvm:transforms
Reported by: kongy

ToT Clang hangs when building under -O1.

```
clang++ test.i -fno-exceptions -O1 -c -emit-llvm
```

The reproducer, `test.i`:

```c++
class MockDevice;
struct sp {
  MockDevice operator*();
};
void memset(void *__dest, int __ch, unsigned __len) {
  long __trans_tmp_1 = __builtin_object_size(__dest, 0);
  __builtin___memset_chk(__dest, __ch, __len, __trans_tmp_1);
}
template <class>
class function;
template <class _Rp, class... _ArgTypes>
class function<_Rp(_ArgTypes...)> {
 public:
  template <class _Fp>
  function operator=(_Fp);
};
template <typename T>
struct hidl_vec {
  hidl_vec() : mSize() { memset(mPad, 0, 0); }
  hidl_vec(hidl_vec &other) { *this = other; }
  hidl_vec &operator=(hidl_vec &other) {
    copyFrom(other, other.mSize);
    return *this;
  }
  T &operator[](unsigned index) { return mBuffer[index]; }
  T* mBuffer;
  unsigned mSize;
  unsigned mPad[];
  template <typename Array>
  void copyFrom(Array &data, unsigned size) {
    mSize = size;
    if (mSize) mBuffer = new T();
    for (int i = 0; i < size; ++i) mBuffer[i] = data[i];
  }
};
struct Capabilities {
  struct OperandPerformance {
    int a, b, c;
  };
  hidl_vec<OperandPerformance> operandPerformance;
};
template <typename>
class Action;
template <typename R, typename... Args>
class Action<R(Args...)> {
  using F = R();
 public:
  template <typename G>
  Action(G fun) {
    fun_ = fun;
  }
  function<F> fun_;
};
struct OnCallSpec {
  OnCallSpec WillByDefault(Action<void()>);
};
struct MockSpec {
  OnCallSpec InternalDefaultActionSetAt();
};
struct MockDevice {
  MockSpec gmock_getCapabilities();
};
sp createMockDevice_mockDevice;
MockDevice createMockDevice() {
  Capabilities getCapabilities_ret;
  (*createMockDevice_mockDevice)
      .gmock_getCapabilities()
      .InternalDefaultActionSetAt()
      .WillByDefault(getCapabilities_ret);
  return *createMockDevice_mockDevice;
}
```

Comments: author: AaronBallman
body: This seems to be hanging somewhere in this vicinity:
```
>	clang.exe!llvm::detail::CheckedInt::from<int,0>(int FromValue) Line 136	C++
 	clang.exe!llvm::detail::CheckedInt::from<enum llvm::IRMemLocation,0>(llvm::IRMemLocation FromValue) Line 143	C++
 	clang.exe!llvm::detail::SafeIntIterator<enum llvm::IRMemLocation,0>::SafeIntIterator<enum llvm::IRMemLocation,0>(llvm::IRMemLocation Value) Line 196	C++
 	clang.exe!llvm::iota_range<enum llvm::IRMemLocation>::iota_range<enum llvm::IRMemLocation>(llvm::IRMemLocation Begin, llvm::IRMemLocation End, bool Inclusive) Line 275	C++
 	clang.exe!llvm::enum_seq_inclusive<enum llvm::IRMemLocation,void>(llvm::IRMemLocation Begin, llvm::IRMemLocation End, llvm::force_iteration_on_noniterable_enum_t __formal) Line 381	C++
 	clang.exe!llvm::MemoryEffectsBase<enum llvm::IRMemLocation>::locations() Line 96	C++
 	clang.exe!llvm::MemoryEffectsBase<enum llvm::IRMemLocation>::MemoryEffectsBase<enum llvm::IRMemLocation>(llvm::ModRefInfo MR) Line 107	C++
 	clang.exe!llvm::MemoryEffectsBase<enum llvm::IRMemLocation>::unknown() Line 113	C++
 	clang.exe!llvm::GlobalsAAResult::getMemoryEffects(const llvm::Function * F) Line 244	C++
 	clang.exe!llvm::AAResults::Model<llvm::GlobalsAAResult>::getMemoryEffects(const llvm::Function * F) Line 784	C++
 	clang.exe!llvm::AAResults::getMemoryEffects(const llvm::Function * F) Line 396	C++
 	clang.exe!llvm::BasicAAResult::getMemoryEffects(const llvm::CallBase * Call, llvm::AAQueryInfo & AAQI) Line 830	C++
 	clang.exe!llvm::AAResults::Model<llvm::BasicAAResult>::getMemoryEffects(const llvm::CallBase * Call, llvm::AAQueryInfo & AAQI) Line 780	C++
 	clang.exe!llvm::AAResults::getMemoryEffects(const llvm::CallBase * Call, llvm::AAQueryInfo & AAQI) Line 377	C++
 	clang.exe!llvm::AAResults::getModRefInfo(const llvm::CallBase * Call, const llvm::MemoryLocation & Loc, llvm::AAQueryInfo & AAQI) Line 230	C++
 	clang.exe!llvm::AAResults::getModRefInfo(const llvm::Instruction * I, const std::optional<llvm::MemoryLocation> & OptLoc, llvm::AAQueryInfo & AAQIP) Line 628	C++
 	clang.exe!llvm::BatchAAResults::getModRefInfo(const llvm::Instruction * I, const std::optional<llvm::MemoryLocation> & OptLoc) Line 646	C++
 	clang.exe!llvm::MemCpyOptPass::processMemSetMemCpyDependence(llvm::MemCpyInst * MemCpy, llvm::MemSetInst * MemSet, llvm::BatchAAResults & BAA) Line 1252	C++
 	clang.exe!llvm::MemCpyOptPass::processMemCpy(llvm::MemCpyInst * M, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction,1,0,void,1,llvm::BasicBlock>,0,0> & BBI) Line 1725	C++
 	clang.exe!llvm::MemCpyOptPass::iterateOnFunction(llvm::Function & F) Line 2013	C++
 	clang.exe!llvm::MemCpyOptPass::runImpl(llvm::Function & F, llvm::TargetLibraryInfo * TLI_, llvm::AAResults * AA_, llvm::AssumptionCache * AC_, llvm::DominatorTree * DT_, llvm::PostDominatorTree * PDT_, llvm::MemorySSA * MSSA_) Line 2070	C++
 	clang.exe!llvm::MemCpyOptPass::run(llvm::Function & F, llvm::AnalysisManager<llvm::Function> & AM) Line 2045	C++
 	clang.exe!llvm::detail::PassModel<llvm::Function,llvm::MemCpyOptPass,llvm::AnalysisManager<llvm::Function>>::run(llvm::Function & IR, llvm::AnalysisManager<llvm::Function> & AM) Line 90	C++
 	clang.exe!llvm::PassManager<llvm::Function,llvm::AnalysisManager<llvm::Function>>::run(llvm::Function & IR, llvm::AnalysisManager<llvm::Function> & AM) Line 85	C++
 	clang.exe!llvm::detail::PassModel<llvm::Function,llvm::PassManager<llvm::Function,llvm::AnalysisManager<llvm::Function>>,llvm::AnalysisManager<llvm::Function>>::run(llvm::Function & IR, llvm::AnalysisManager<llvm::Function> & AM) Line 90	C++
 	clang.exe!llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC & C, llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &> & AM, llvm::LazyCallGraph & CG, llvm::CGSCCUpdateResult & UR) Line 543	C++
 	clang.exe!llvm::detail::PassModel<llvm::LazyCallGraph::SCC,llvm::CGSCCToFunctionPassAdaptor,llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &>,llvm::LazyCallGraph &,llvm::CGSCCUpdateResult &>::run(llvm::LazyCallGraph::SCC & IR, llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &> & AM, llvm::LazyCallGraph & <ExtraArgs_0>, llvm::CGSCCUpdateResult & <ExtraArgs_1>) Line 90	C++
 	clang.exe!llvm::PassManager<llvm::LazyCallGraph::SCC,llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &>,llvm::LazyCallGraph &,llvm::CGSCCUpdateResult &>::run(llvm::LazyCallGraph::SCC & InitialC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &> & AM, llvm::LazyCallGraph & G, llvm::CGSCCUpdateResult & UR) Line 90	C++
 	clang.exe!llvm::detail::PassModel<llvm::LazyCallGraph::SCC,llvm::PassManager<llvm::LazyCallGraph::SCC,llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &>,llvm::LazyCallGraph &,llvm::CGSCCUpdateResult &>,llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &>,llvm::LazyCallGraph &,llvm::CGSCCUpdateResult &>::run(llvm::LazyCallGraph::SCC & IR, llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &> & AM, llvm::LazyCallGraph & <ExtraArgs_0>, llvm::CGSCCUpdateResult & <ExtraArgs_1>) Line 90	C++
 	clang.exe!llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC & InitialC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &> & AM, llvm::LazyCallGraph & CG, llvm::CGSCCUpdateResult & UR) Line 415	C++
 	clang.exe!llvm::detail::PassModel<llvm::LazyCallGraph::SCC,llvm::DevirtSCCRepeatedPass,llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &>,llvm::LazyCallGraph &,llvm::CGSCCUpdateResult &>::run(llvm::LazyCallGraph::SCC & IR, llvm::AnalysisManager<llvm::LazyCallGraph::SCC,llvm::LazyCallGraph &> & AM, llvm::LazyCallGraph & <ExtraArgs_0>, llvm::CGSCCUpdateResult & <ExtraArgs_1>) Line 90	C++
 	clang.exe!llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module & M, llvm::AnalysisManager<llvm::Module> & AM) Line 277	C++
 	clang.exe!llvm::detail::PassModel<llvm::Module,llvm::ModuleToPostOrderCGSCCPassAdaptor,llvm::AnalysisManager<llvm::Module>>::run(llvm::Module & IR, llvm::AnalysisManager<llvm::Module> & AM) Line 90	C++
 	clang.exe!llvm::PassManager<llvm::Module,llvm::AnalysisManager<llvm::Module>>::run(llvm::Module & IR, llvm::AnalysisManager<llvm::Module> & AM) Line 85	C++
 	clang.exe!llvm::ModuleInlinerWrapperPass::run(llvm::Module & M, llvm::AnalysisManager<llvm::Module> & MAM) Line 631	C++
 	clang.exe!llvm::detail::PassModel<llvm::Module,llvm::ModuleInlinerWrapperPass,llvm::AnalysisManager<llvm::Module>>::run(llvm::Module & IR, llvm::AnalysisManager<llvm::Module> & AM) Line 90	C++
 	clang.exe!llvm::PassManager<llvm::Module,llvm::AnalysisManager<llvm::Module>>::run(llvm::Module & IR, llvm::AnalysisManager<llvm::Module> & AM) Line 85	C++
 	clang.exe!`anonymous namespace'::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction Action, std::unique_ptr<llvm::raw_pwrite_stream,std::default_delete<llvm::raw_pwrite_stream>> & OS, std::unique_ptr<llvm::ToolOutputFile,std::default_delete<llvm::ToolOutputFile>> & ThinLinkOS, clang::BackendConsumer * BC) Line 1114	C++
 	clang.exe!`anonymous namespace'::EmitAssemblyHelper::EmitAssembly(clang::BackendAction Action, std::unique_ptr<llvm::raw_pwrite_stream,std::default_delete<llvm::raw_pwrite_stream>> OS, clang::BackendConsumer * BC) Line 1180	C++
 	clang.exe!clang::EmitBackendOutput(clang::DiagnosticsEngine & Diags, const clang::HeaderSearchOptions & HeaderOpts, const clang::CodeGenOptions & CGOpts, const clang::TargetOptions & TOpts, const clang::LangOptions & LOpts, llvm::StringRef TDesc, llvm::Module * M, clang::BackendAction Action, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, std::unique_ptr<llvm::raw_pwrite_stream,std::default_delete<llvm::raw_pwrite_stream>> OS, clang::BackendConsumer * BC) Line 1341	C++
 	clang.exe!clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext & C) Line 354	C++
 	clang.exe!clang::ParseAST(clang::Sema & S, bool PrintStats, bool SkipFunctionBodies) Line 183	C++
 	clang.exe!clang::ASTFrontendAction::ExecuteAction() Line 1192	C++
 	clang.exe!clang::CodeGenAction::ExecuteAction() Line 1144	C++
 	clang.exe!clang::FrontendAction::Execute() Line 1078	C++
 	clang.exe!clang::CompilerInstance::ExecuteAction(clang::FrontendAction & Act) Line 1061	C++
 	clang.exe!clang::ExecuteCompilerInvocation(clang::CompilerInstance * Clang) Line 280	C++
 	clang.exe!cc1_main(llvm::ArrayRef<char const *> Argv, const char * Argv0, void * MainAddr) Line 283	C++
 	clang.exe!ExecuteCC1Tool(llvm::SmallVectorImpl<char const *> & ArgV, const llvm::ToolContext & ToolContext) Line 215	C++
 	clang.exe!clang_main(int Argc, char * * Argv, const llvm::ToolContext & ToolContext) Line 256	C++
 	clang.exe!main(int argc, char * * argv) Line 17	C++
 	clang.exe!invoke_main() Line 79	C++
 	clang.exe!__scrt_common_main_seh() Line 288	C++
 	clang.exe!__scrt_common_main() Line 331	C++
 	clang.exe!mainCRTStartup(void * __formal) Line 17	C++
 	kernel32.dll!00007ff830e07344()	Unknown
 	ntdll.dll!00007ff83149cc91()	Unknown
```
author: nikic
body: Reduced:
```llvm
; RUN: opt -S -passes=memcpyopt < %s
define void @test(ptr %p, ptr noalias %p2) {
  call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 1, i1 false)
  %zero.ext = zext i32 0 to i64
  %mul = mul i64 %zero.ext, 1
  call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %mul, i1 false)
  ret void
}
```
author: nikic
body: This is an infinite loop in the processMemSetMemCpyDependence() transform. I've tried to mitigate this in the past, but it looks like the mitigation doesn't work for this case. I guess we'll have to add an isKnownNonZero() check to prevent it.

Fix patch:
commit 71051deff27928cff908ea794e09806eee662801
Author: Nikita Popov <npopov@redhat.com>
Date:   Mon Jul 15 09:41:11 2024 +0200

    [MemCpyOpt] Fix infinite loop in memset+memcpy fold (#98638)
    
    For the case where the memcpy size is zero, this transform is a complex
    no-op. This can lead to an infinite loop when the size is zero in a way
    that BasicAA understands, because it can still understand that dst and
    dst + src_size are MustAlias.
    
    I've tried to mitigate this before using the isZeroSize() check, but we
    can hit cases where InstSimplify doesn't understand that the size is
    zero, but BasicAA does.
    
    As such, this bites the bullet and adds an explicit isKnownNonZero()
    check to guard against no-op transforms.
    
    Fixes https://github.com/llvm/llvm-project/issues/98610.

diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 4063762c88a2..cee34f0a6da1 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1296,6 +1296,15 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
   if (!BAA.isMustAlias(MemSet->getDest(), MemCpy->getDest()))
     return false;
 
+  // Don't perform the transform if src_size may be zero. In that case, the
+  // transform is essentially a complex no-op and may lead to an infinite
+  // loop if BasicAA is smart enough to understand that dst and dst + src_size
+  // are still MustAlias after the transform.
+  Value *SrcSize = MemCpy->getLength();
+  if (!isKnownNonZero(SrcSize,
+                      SimplifyQuery(MemCpy->getDataLayout(), DT, AC, MemCpy)))
+    return false;
+
   // Check that src and dst of the memcpy aren't the same. While memcpy
   // operands cannot partially overlap, exact equality is allowed.
   if (isModSet(BAA.getModRefInfo(MemCpy, MemoryLocation::getForSource(MemCpy))))
@@ -1312,7 +1321,6 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
   // Use the same i8* dest as the memcpy, killing the memset dest if different.
   Value *Dest = MemCpy->getRawDest();
   Value *DestSize = MemSet->getLength();
-  Value *SrcSize = MemCpy->getLength();
 
   if (mayBeVisibleThroughUnwinding(Dest, MemSet, MemCpy))
     return false;
@@ -1726,8 +1734,7 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
     return true;
   }
 
-  // If the size is zero, remove the memcpy. This also prevents infinite loops
-  // in processMemSetMemCpyDependence, which is a no-op for zero-length memcpys.
+  // If the size is zero, remove the memcpy.
   if (isZeroSize(M->getLength())) {
     ++BBI;
     eraseInstruction(M);


Regression tests:
file: llvm/test/Transforms/MemCpyOpt/memcpy-zero-size.ll
commands: opt -S -passes=memcpyopt < %s
tests: test_name: pr64886
test_body: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

define void @pr64886(i64 %len, ptr noalias %p) {
  call void @llvm.memset.p0.i64(ptr inttoptr (i64 -1 to ptr), i8 0, i64 %len, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr inttoptr (i64 -1 to ptr), ptr %p, i64 poison, i1 false)
  ret void
}

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

test_name: pr98610
test_body: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

define void @pr98610(ptr %p, ptr noalias %p2) {
  call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 1, i1 false)
  %zero.ext = zext i32 0 to i64
  %mul = mul i64 %zero.ext, 1
  call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %mul, i1 false)
  ret void
}

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

file: llvm/test/Transforms/MemCpyOpt/memset-memcpy-dbgloc.ll
commands: opt -passes=memcpyopt -S %s -verify-memoryssa
tests: test_name: test_constant
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

@C = external constant [0 x i8]

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

define void @test_constant(i64 %src_size, ptr %dst, i64 %dst_size, i8 %c) !dbg !5 {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false), !dbg !11
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr @C, i64 %src_size, i1 false), !dbg !12
  ret void, !dbg !13
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

!llvm.dbg.cu = !{!0}
!llvm.debugify = !{!2, !3}
!llvm.module.flags = !{!4}

!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
!1 = !DIFile(filename: "memset-memcpy-dbgloc.ll", directory: "/")
!2 = !{i32 3}
!3 = !{i32 1}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !DISubprogram(name: "test_constant", linkageName: "test_constant", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
!6 = !DISubroutineType(types: !7)
!7 = !{}
!8 = !{!9}
!9 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 3, type: !10)
!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
!11 = !DILocation(line: 1, column: 1, scope: !5)
!12 = !DILocation(line: 2, column: 1, scope: !5)
!13 = !DILocation(line: 3, column: 1, scope: !5)

file: llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll
commands: opt -passes=memcpyopt -S %s -verify-memoryssa
tests: test_name: test_different_types_i32_i128
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_different_types_i32_i128(ptr noalias %dst, ptr %src, i32 %dst_size, i128 %src_size, i8 %c) {
  %non.zero = icmp ne i128 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i32(ptr %dst, i8 %c, i32 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i128(ptr %dst, ptr %src, i128 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #0

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i128(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i128, i1 immarg) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_missing_noalias
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_missing_noalias(ptr %src, i64 %src_size, ptr %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_different_types_i128_i32
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_different_types_i128_i32(ptr noalias %dst, ptr %src, i128 %dst_size, i32 %src_size, i8 %c) {
  %non.zero = icmp ne i32 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i128(ptr %dst, i8 %c, i128 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i32(ptr %dst, ptr %src, i32 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #0

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i128(ptr nocapture writeonly, i8, i128, i1 immarg) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_align_memcpy
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_align_memcpy(ptr %src, ptr noalias %dst, i64 %dst_size) {
  call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dst, ptr align 8 %src, i64 80, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

test_name: test_different_dst
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_different_dst(ptr noalias %dst2, ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst2, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_non_i8_dst_type
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_non_i8_dst_type(ptr %src, i64 %src_size, ptr noalias %dst_pi64, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst_pi64, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst_pi64, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_different_types_i64_i32
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_different_types_i64_i32(ptr noalias %dst, ptr %src, i64 %dst_size, i32 %src_size, i8 %c) {
  %non.zero = icmp ne i32 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i32(ptr %dst, ptr %src, i32 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_intermediate_write
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

%struct = type { [8 x i8], [8 x i8] }

define void @test_intermediate_write(ptr %b) {
  %a = alloca %struct, align 8
  %a1 = getelementptr %struct, ptr %a, i32 0, i32 1, i32 0
  call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 16, i1 false)
  store i8 1, ptr %a1, align 1
  call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 8, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

test_name: test
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_same_dynamic_size
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_same_dynamic_size(ptr noalias %src, ptr noalias %dst, i64 %size, i8 %c) {
  %non.zero = icmp ne i64 %size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_weird_element_type
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_weird_element_type(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_throwing_call
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_throwing_call(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @call() #3
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

declare void @call()

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
attributes #3 = { memory(none) }

test_name: test_same_const_size
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_same_const_size(ptr noalias %src, ptr noalias %dst, i8 %c) {
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 16, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 16, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

test_name: test_must_alias_different_size
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_must_alias_different_size(ptr noalias %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  %gep1 = getelementptr i8, ptr %dst, i64 16
  call void @llvm.memset.p0.i64(ptr %gep1, i8 %c, i64 %dst_size, i1 false)
  %gep2 = getelementptr i8, ptr %dst, i64 16
  call void @llvm.memcpy.p0.p0.i64(ptr %gep2, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_throwing_call_alloca
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_throwing_call_alloca(ptr %src, i64 %src_size, i64 %dst_size, i8 %c) {
  %dst = alloca i8, align 1
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @call() #3
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

declare void @call()

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
attributes #3 = { memory(none) }

test_name: test_addrspace
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_addrspace(ptr addrspace(1) %src, i64 %src_size, ptr addrspace(1) noalias %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p1.i64(ptr addrspace(1) %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %dst, ptr addrspace(1) %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p1.i64(ptr addrspace(1) nocapture writeonly, i8, i64, i1 immarg) #0

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) noalias nocapture writeonly, ptr addrspace(1) noalias nocapture readonly, i64, i1 immarg) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_constant
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

@C = external constant [0 x i8]

define void @test_constant(i64 %src_size, ptr %dst, i64 %dst_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr @C, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_different_types_i32_i64
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_different_types_i32_i64(ptr noalias %dst, ptr %src, i32 %dst_size, i64 %src_size, i8 %c) {
  %non.zero = icmp ne i64 %src_size, 0
  call void @llvm.assume(i1 %non.zero)
  call void @llvm.memset.p0.i32(ptr %dst, i8 %c, i32 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, 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: write)
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #2

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

test_name: test_must_alias_same_size
test_body: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

define void @test_must_alias_same_size(ptr noalias %src, ptr noalias %dst, i8 %c) {
  %gep1 = getelementptr i8, ptr %dst, i64 16
  call void @llvm.memset.p0.i64(ptr %gep1, i8 %c, i64 16, i1 false)
  %gep2 = getelementptr i8, ptr %dst, i64 16
  call void @llvm.memcpy.p0.p0.i64(ptr %gep2, ptr %src, i64 16, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

file: llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll
commands: opt -passes=memcpyopt -S %s -verify-memoryssa
tests: test_name: test_memset_memcpy
test_body: define void @test_memset_memcpy(ptr %src, i64 range(i64 1, 42) %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
  call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

; 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) #1

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }