From 6d1485e974dfdcf23ba302595e069d9eecbb8162 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Wed, 20 May 2015 23:55:16 +0000 Subject: [PATCH] [MemCpyOpt] Don't move the memset when optimizing memset+memcpy. Fixes PR23599, another miscompile introduced by r235232: when there is another dependency on the destination of the created memset (i.e., the part of the original destination that the memcpy doesn't depend on) between the memcpy and the original memset, we would insert the created memset after the memcpy, and thus after the other dependency. Instead, insert the created memset right after the old one. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237858 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 2 +- .../MemCpyOpt/memset-memcpy-redundant-memset.ll | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index 7ac968159c5..ae5501e5884 100644 --- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -874,7 +874,7 @@ bool MemCpyOpt::processMemSetMemCpyDependence(MemCpyInst *MemCpy, if (ConstantInt *SrcSizeC = dyn_cast(SrcSize)) Align = MinAlign(SrcSizeC->getZExtValue(), DestAlign); - IRBuilder<> Builder(MemCpy->getNextNode()); + IRBuilder<> Builder(MemSet->getNextNode()); // If the sizes have different types, zext the smaller one. if (DestSize->getType() != SrcSize->getType()) { diff --git a/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll b/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll index 983ec44335f..25411f26982 100644 --- a/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll +++ b/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll @@ -3,12 +3,12 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; CHECK-LABEL: define void @test -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ; CHECK-DAG: [[DST:%[0-9]+]] = getelementptr i8, i8* %dst, i64 %src_size ; CHECK-DAG: [[ULE:%[0-9]+]] = icmp ule i64 %dst_size, %src_size ; CHECK-DAG: [[SIZEDIFF:%[0-9]+]] = sub i64 %dst_size, %src_size ; CHECK-DAG: [[SIZE:%[0-9]+]] = select i1 [[ULE]], i64 0, i64 [[SIZEDIFF]] ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DST]], i8 %c, i64 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ; CHECK-NEXT: ret void define void @test(i8* %src, i64 %src_size, i8* %dst, i64 %dst_size, i8 %c) { call void @llvm.memset.p0i8.i64(i8* %dst, i8 %c, i64 %dst_size, i32 1, i1 false) @@ -17,13 +17,13 @@ define void @test(i8* %src, i64 %src_size, i8* %dst, i64 %dst_size, i8 %c) { } ; CHECK-LABEL: define void @test_different_types_i32_i64 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ; CHECK-DAG: [[DSTSIZE:%[0-9]+]] = zext i32 %dst_size to i64 ; CHECK-DAG: [[DST:%[0-9]+]] = getelementptr i8, i8* %dst, i64 %src_size ; CHECK-DAG: [[ULE:%[0-9]+]] = icmp ule i64 [[DSTSIZE]], %src_size ; CHECK-DAG: [[SIZEDIFF:%[0-9]+]] = sub i64 [[DSTSIZE]], %src_size ; CHECK-DAG: [[SIZE:%[0-9]+]] = select i1 [[ULE]], i64 0, i64 [[SIZEDIFF]] ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DST]], i8 %c, i64 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ; CHECK-NEXT: ret void define void @test_different_types_i32_i64(i8* %dst, i8* %src, i32 %dst_size, i64 %src_size, i8 %c) { call void @llvm.memset.p0i8.i32(i8* %dst, i8 %c, i32 %dst_size, i32 1, i1 false) @@ -32,13 +32,13 @@ define void @test_different_types_i32_i64(i8* %dst, i8* %src, i32 %dst_size, i64 } ; CHECK-LABEL: define void @test_different_types_i128_i32 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %src_size, i32 1, i1 false) ; CHECK-DAG: [[SRCSIZE:%[0-9]+]] = zext i32 %src_size to i128 ; CHECK-DAG: [[DST:%[0-9]+]] = getelementptr i8, i8* %dst, i128 [[SRCSIZE]] ; CHECK-DAG: [[ULE:%[0-9]+]] = icmp ule i128 %dst_size, [[SRCSIZE]] ; CHECK-DAG: [[SIZEDIFF:%[0-9]+]] = sub i128 %dst_size, [[SRCSIZE]] ; CHECK-DAG: [[SIZE:%[0-9]+]] = select i1 [[ULE]], i128 0, i128 [[SIZEDIFF]] ; CHECK-NEXT: call void @llvm.memset.p0i8.i128(i8* [[DST]], i8 %c, i128 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %src_size, i32 1, i1 false) ; CHECK-NEXT: ret void define void @test_different_types_i128_i32(i8* %dst, i8* %src, i128 %dst_size, i32 %src_size, i8 %c) { call void @llvm.memset.p0i8.i128(i8* %dst, i8 %c, i128 %dst_size, i32 1, i1 false) @@ -47,13 +47,13 @@ define void @test_different_types_i128_i32(i8* %dst, i8* %src, i128 %dst_size, i } ; CHECK-LABEL: define void @test_different_types_i32_i128 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i128(i8* %dst, i8* %src, i128 %src_size, i32 1, i1 false) ; CHECK-DAG: [[DSTSIZE:%[0-9]+]] = zext i32 %dst_size to i128 ; CHECK-DAG: [[DST:%[0-9]+]] = getelementptr i8, i8* %dst, i128 %src_size ; CHECK-DAG: [[ULE:%[0-9]+]] = icmp ule i128 [[DSTSIZE]], %src_size ; CHECK-DAG: [[SIZEDIFF:%[0-9]+]] = sub i128 [[DSTSIZE]], %src_size ; CHECK-DAG: [[SIZE:%[0-9]+]] = select i1 [[ULE]], i128 0, i128 [[SIZEDIFF]] ; CHECK-NEXT: call void @llvm.memset.p0i8.i128(i8* [[DST]], i8 %c, i128 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i128(i8* %dst, i8* %src, i128 %src_size, i32 1, i1 false) ; CHECK-NEXT: ret void define void @test_different_types_i32_i128(i8* %dst, i8* %src, i32 %dst_size, i128 %src_size, i8 %c) { call void @llvm.memset.p0i8.i32(i8* %dst, i8 %c, i32 %dst_size, i32 1, i1 false) @@ -62,13 +62,13 @@ define void @test_different_types_i32_i128(i8* %dst, i8* %src, i32 %dst_size, i1 } ; CHECK-LABEL: define void @test_different_types_i64_i32 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %src_size, i32 1, i1 false) ; CHECK-DAG: [[SRCSIZE:%[0-9]+]] = zext i32 %src_size to i64 ; CHECK-DAG: [[DST:%[0-9]+]] = getelementptr i8, i8* %dst, i64 [[SRCSIZE]] ; CHECK-DAG: [[ULE:%[0-9]+]] = icmp ule i64 %dst_size, [[SRCSIZE]] ; CHECK-DAG: [[SIZEDIFF:%[0-9]+]] = sub i64 %dst_size, [[SRCSIZE]] ; CHECK-DAG: [[SIZE:%[0-9]+]] = select i1 [[ULE]], i64 0, i64 [[SIZEDIFF]] ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DST]], i8 %c, i64 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %src_size, i32 1, i1 false) ; CHECK-NEXT: ret void define void @test_different_types_i64_i32(i8* %dst, i8* %src, i64 %dst_size, i32 %src_size, i8 %c) { call void @llvm.memset.p0i8.i64(i8* %dst, i8 %c, i64 %dst_size, i32 1, i1 false) @@ -102,12 +102,12 @@ define void @test_align_memcpy(i8* %src, i8* %dst, i64 %dst_size) { ; CHECK-LABEL: define void @test_non_i8_dst_type ; CHECK-NEXT: %dst = bitcast i64* %dst_pi64 to i8* -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ; CHECK-DAG: [[DST:%[0-9]+]] = getelementptr i8, i8* %dst, i64 %src_size ; CHECK-DAG: [[ULE:%[0-9]+]] = icmp ule i64 %dst_size, %src_size ; CHECK-DAG: [[SIZEDIFF:%[0-9]+]] = sub i64 %dst_size, %src_size ; CHECK-DAG: [[SIZE:%[0-9]+]] = select i1 [[ULE]], i64 0, i64 [[SIZEDIFF]] ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DST]], i8 %c, i64 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ; CHECK-NEXT: ret void define void @test_non_i8_dst_type(i8* %src, i64 %src_size, i64* %dst_pi64, i64 %dst_size, i8 %c) { %dst = bitcast i64* %dst_pi64 to i8*