From 7216ccc3f34a97ea07354fe0bb61b782d5f1be18 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Sat, 18 Apr 2015 17:57:41 +0000 Subject: [PATCH] [MemCpyOpt] Promote both memset/memcpy sizes if differently typed. Followup to r235232, which caused PR23278. We can't assume the memset and memcpy sizes have the same type, as nothing in the language reference prevents that. Instead, zext both to i64 if they disagree. While there, robustify tests by using i8 %c rather than i8 0 for the memset character. llvm-svn: 235258 --- llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 6 ++++ .../MemCpyOpt/memset-memcpy-redundant-memset.ll | 38 ++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp index 72127bb..550757a 100644 --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -876,6 +876,12 @@ bool MemCpyOpt::processMemSetMemCpyDependence(MemCpyInst *MemCpy, IRBuilder<> Builder(MemCpy->getNextNode()); + // If the sizes have different types (i32 vs i64), promote both to i64. + if (DestSize->getType() != SrcSize->getType()) { + DestSize = Builder.CreateZExt(DestSize, Builder.getInt64Ty()); + SrcSize = Builder.CreateZExt(SrcSize, Builder.getInt64Ty()); + } + Value *MemsetLen = Builder.CreateSelect(Builder.CreateICmpULE(DestSize, SrcSize), ConstantInt::getNullValue(DestSize->getType()), diff --git a/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll b/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll index 5fa5a91..cc94f58 100644 --- a/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll +++ b/llvm/test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll @@ -8,14 +8,44 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; 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 0, i64 [[SIZE]], i32 1, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DST]], i8 %c, i64 [[SIZE]], i32 1, i1 false) ; CHECK-NEXT: ret void -define void @test(i8* %src, i64 %src_size, i8* %dst, i64 %dst_size) { - call void @llvm.memset.p0i8.i64(i8* %dst, i8 0, i64 %dst_size, i32 1, i1 false) +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) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) + ret void +} + +; 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: 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) call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %src_size, i32 1, i1 false) ret void } +; 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: 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) + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %src_size, i32 1, i1 false) + ret void +} + ; CHECK-LABEL: define void @test_align_same ; CHECK: call void @llvm.memset.p0i8.i64(i8* {{.*}}, i8 0, i64 {{.*}}, i32 8, i1 false) define void @test_align_same(i8* %src, i8* %dst, i64 %dst_size) { @@ -52,3 +82,5 @@ define void @test_different_dst(i8* %dst2, i8* %src, i64 %src_size, i8* %dst, i6 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) -- 2.7.4