[MemCpyOpt] Don't force i64 when promoting memset/memcpy sizes.
authorAhmed Bougacha <ahmed.bougacha@gmail.com>
Sat, 18 Apr 2015 23:06:04 +0000 (23:06 +0000)
committerAhmed Bougacha <ahmed.bougacha@gmail.com>
Sat, 18 Apr 2015 23:06:04 +0000 (23:06 +0000)
Harden r235258 to support any integer bitwidth.  The quick glance at
the reference made me think only i32 and i64 were valid types, but
they're not special, so any overload is legal.

Thanks to David Majnemer for noticing!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235261 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/MemCpyOptimizer.cpp
test/Transforms/MemCpyOpt/memset-memcpy-redundant-memset.ll

index 550757a09f5ef2a08b4eb290d58bc7a3cf591d8f..563e49c0190c388100a2050257e735f70180df7b 100644 (file)
@@ -876,10 +876,13 @@ bool MemCpyOpt::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
 
   IRBuilder<> Builder(MemCpy->getNextNode());
 
-  // If the sizes have different types (i32 vs i64), promote both to i64.
+  // If the sizes have different types, zext the smaller one.
   if (DestSize->getType() != SrcSize->getType()) {
-    DestSize = Builder.CreateZExt(DestSize, Builder.getInt64Ty());
-    SrcSize = Builder.CreateZExt(SrcSize, Builder.getInt64Ty());
+    if (DestSize->getType()->getIntegerBitWidth() >
+        SrcSize->getType()->getIntegerBitWidth())
+      SrcSize = Builder.CreateZExt(SrcSize, DestSize->getType());
+    else
+      DestSize = Builder.CreateZExt(DestSize, SrcSize->getType());
   }
 
   Value *MemsetLen =
index cc94f58dbfbd1a9d5364b316d33935ae61da9e94..5d3ef6bfd00d5c7e3540cd48ec3065f722cefbb0 100644 (file)
@@ -31,6 +31,36 @@ define void @test_different_types_i32_i64(i8* %dst, i8* %src, i32 %dst_size, i64
   ret void
 }
 
+; 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: 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)
+  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_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: 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)
+  call void @llvm.memcpy.p0i8.p0i8.i128(i8* %dst, i8* %src, i128 %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
@@ -84,3 +114,5 @@ 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)
+declare void @llvm.memset.p0i8.i128(i8* nocapture, i8, i128, i32, i1)
+declare void @llvm.memcpy.p0i8.p0i8.i128(i8* nocapture, i8* nocapture readonly, i128, i32, i1)