diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -940,6 +940,11 @@ return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name); } + /// Create call to the usub_sat intrinsic. + CallInst *CreateUSubSat(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateBinaryIntrinsic(Intrinsic::usub_sat, LHS, RHS, nullptr, Name); + } + /// Create a call to the arithmetic_fence intrinsic. CallInst *CreateArithmeticFence(Value *Val, Type *DstType, const Twine &Name = "") { diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -1276,10 +1276,7 @@ DestSize = Builder.CreateZExt(DestSize, SrcSize->getType()); } - Value *Ule = Builder.CreateICmpULE(DestSize, SrcSize); - Value *SizeDiff = Builder.CreateSub(DestSize, SrcSize); - Value *MemsetLen = Builder.CreateSelect( - Ule, ConstantInt::getNullValue(DestSize->getType()), SizeDiff); + Value *MemsetLen = Builder.CreateUSubSat(DestSize, SrcSize, "memset.len"); unsigned DestAS = Dest->getType()->getPointerAddressSpace(); Instruction *NewMemSet = Builder.CreateMemSet( Builder.CreateGEP( diff --git a/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll b/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll --- a/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll +++ b/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll @@ -7,11 +7,9 @@ define void @test_constant(i64 %src_size, ptr %dst, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_constant( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr @C, i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -22,11 +20,9 @@ define void @test(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -38,11 +34,9 @@ define void @test_different_types_i32_i64(ptr noalias %dst, ptr %src, i32 %dst_size, i64 %src_size, i8 %c) { ; CHECK-LABEL: @test_different_types_i32_i64( ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[DST_SIZE:%.*]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i64 [[TMP1]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP3]] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP5]], i8 [[C:%.*]], i64 [[TMP4]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[TMP1]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP2]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -54,11 +48,9 @@ define void @test_different_types_i128_i32(ptr noalias %dst, ptr %src, i128 %dst_size, i32 %src_size, i8 %c) { ; CHECK-LABEL: @test_different_types_i128_i32( ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SRC_SIZE:%.*]] to i128 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i128 [[DST_SIZE:%.*]], [[TMP1]] -; CHECK-NEXT: [[TMP3:%.*]] = sub i128 [[DST_SIZE]], [[TMP1]] -; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i128 0, i128 [[TMP3]] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i128 [[TMP1]] -; CHECK-NEXT: call void @llvm.memset.p0.i128(ptr align 1 [[TMP5]], i8 [[C:%.*]], i128 [[TMP4]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i128 @llvm.usub.sat.i128(i128 [[DST_SIZE:%.*]], i128 [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[DST:%.*]], i128 [[TMP1]] +; CHECK-NEXT: call void @llvm.memset.p0.i128(ptr align 1 [[TMP2]], i8 [[C:%.*]], i128 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[DST]], ptr [[SRC:%.*]], i32 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -70,11 +62,9 @@ define void @test_different_types_i32_i128(ptr noalias %dst, ptr %src, i32 %dst_size, i128 %src_size, i8 %c) { ; CHECK-LABEL: @test_different_types_i32_i128( ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[DST_SIZE:%.*]] to i128 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i128 [[TMP1]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = sub i128 [[TMP1]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i128 0, i128 [[TMP3]] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i128 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i128(ptr align 1 [[TMP5]], i8 [[C:%.*]], i128 [[TMP4]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i128 @llvm.usub.sat.i128(i128 [[TMP1]], i128 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[DST:%.*]], i128 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i128(ptr align 1 [[TMP2]], i8 [[C:%.*]], i128 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i128(ptr [[DST]], ptr [[SRC:%.*]], i128 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -86,11 +76,9 @@ define void @test_different_types_i64_i32(ptr noalias %dst, ptr %src, i64 %dst_size, i32 %src_size, i8 %c) { ; CHECK-LABEL: @test_different_types_i64_i32( ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SRC_SIZE:%.*]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[TMP1]] -; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[DST_SIZE]], [[TMP1]] -; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP3]] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[TMP1]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP5]], i8 [[C:%.*]], i64 [[TMP4]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[TMP1]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP2]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[DST]], ptr [[SRC:%.*]], i32 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -101,11 +89,9 @@ define void @test_align_same(ptr %src, ptr noalias %dst, i64 %dst_size) { ; CHECK-LABEL: @test_align_same( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], 80 -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], 80 -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 80 -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP4]], i8 0, i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 80) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 80 +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP1]], i8 0, i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 80, i1 false) ; CHECK-NEXT: ret void ; @@ -116,11 +102,9 @@ define void @test_align_min(ptr %src, ptr noalias %dst, i64 %dst_size) { ; CHECK-LABEL: @test_align_min( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], 36 -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], 36 -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 36 -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP4]], i8 0, i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 36) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 36 +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP1]], i8 0, i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 36, i1 false) ; CHECK-NEXT: ret void ; @@ -131,11 +115,9 @@ define void @test_align_memcpy(ptr %src, ptr noalias %dst, i64 %dst_size) { ; CHECK-LABEL: @test_align_memcpy( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], 80 -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], 80 -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 80 -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP4]], i8 0, i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 80) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 80 +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP1]], i8 0, i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DST]], ptr align 8 [[SRC:%.*]], i64 80, i1 false) ; CHECK-NEXT: ret void ; @@ -146,12 +128,10 @@ define void @test_non_i8_dst_type(ptr %src, i64 %src_size, ptr noalias %dst_pi64, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_non_i8_dst_type( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST_PI64:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST_PI64:%.*]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST_PI64:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST_PI64]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; call void @llvm.memset.p0.i64(ptr %dst_pi64, i8 %c, i64 %dst_size, i1 false) @@ -207,7 +187,7 @@ define void @test_throwing_call(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_throwing_call( ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[DST:%.*]], i8 [[C:%.*]], i64 [[DST_SIZE:%.*]], i1 false) -; CHECK-NEXT: call void @call() #[[ATTR2:[0-9]+]] +; CHECK-NEXT: call void @call() #[[ATTR3:[0-9]+]] ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE:%.*]], i1 false) ; CHECK-NEXT: ret void ; @@ -220,12 +200,10 @@ define void @test_throwing_call_alloca(ptr %src, i64 %src_size, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_throwing_call_alloca( ; CHECK-NEXT: [[DST:%.*]] = alloca i8, align 1 -; CHECK-NEXT: call void @call() #[[ATTR2]] -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: call void @call() #[[ATTR3]] +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -288,11 +266,9 @@ ; CHECK-LABEL: @test_must_alias_different_size( ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 16 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[DST]], i64 16 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[GEP2]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[GEP2]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[GEP2]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -305,11 +281,9 @@ define void @test_weird_element_type(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_weird_element_type( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP5]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; @@ -320,11 +294,9 @@ define void @test_addrspace(ptr addrspace(1) %src, i64 %src_size, ptr addrspace(1) noalias %dst, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_addrspace( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr addrspace(1) [[DST:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr addrspace(1) [[DST:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) [[DST]], ptr addrspace(1) [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll b/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll --- a/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll +++ b/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll @@ -3,11 +3,9 @@ define void @test_memset_memcpy(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) { ; CHECK-LABEL: @test_memset_memcpy( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]] -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] -; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false) +; CHECK-NEXT: [[MEMSET_LEN:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[DST_SIZE:%.*]], i64 [[SRC_SIZE:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]] +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 [[C:%.*]], i64 [[MEMSET_LEN]], i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false) ; CHECK-NEXT: ret void ;