1; RUN: opt -memcpyopt -S < %s | FileCheck %s 2 3target datalayout = "e-i64:64-f80:128-n8:16:32:64" 4target triple = "x86_64-unknown-linux-gnu" 5 6%S = type { i8*, i8, i32 } 7 8define void @copy(%S* %src, %S* %dst) { 9; CHECK-LABEL: copy 10; CHECK-NOT: load 11; CHECK: call void @llvm.memmove.p0i8.p0i8.i64 12; CHECK-NEXT: ret void 13 %1 = load %S, %S* %src 14 store %S %1, %S* %dst 15 ret void 16} 17 18define void @noaliassrc(%S* noalias %src, %S* %dst) { 19; CHECK-LABEL: noaliassrc 20; CHECK-NOT: load 21; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 22; CHECK-NEXT: ret void 23 %1 = load %S, %S* %src 24 store %S %1, %S* %dst 25 ret void 26} 27 28define void @noaliasdst(%S* %src, %S* noalias %dst) { 29; CHECK-LABEL: noaliasdst 30; CHECK-NOT: load 31; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 32; CHECK-NEXT: ret void 33 %1 = load %S, %S* %src 34 store %S %1, %S* %dst 35 ret void 36} 37 38define void @destroysrc(%S* %src, %S* %dst) { 39; CHECK-LABEL: destroysrc 40; CHECK: load %S, %S* %src 41; CHECK: call void @llvm.memset.p0i8.i64 42; CHECK-NEXT: store %S %1, %S* %dst 43; CHECK-NEXT: ret void 44 %1 = load %S, %S* %src 45 store %S zeroinitializer, %S* %src 46 store %S %1, %S* %dst 47 ret void 48} 49 50define void @destroynoaliassrc(%S* noalias %src, %S* %dst) { 51; CHECK-LABEL: destroynoaliassrc 52; CHECK-NOT: load 53; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 54; CHECK-NEXT: call void @llvm.memset.p0i8.i64 55; CHECK-NEXT: ret void 56 %1 = load %S, %S* %src 57 store %S zeroinitializer, %S* %src 58 store %S %1, %S* %dst 59 ret void 60} 61 62define void @copyalias(%S* %src, %S* %dst) { 63; CHECK-LABEL: copyalias 64; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %S, %S* %src 65; CHECK-NOT: load 66; CHECK: call void @llvm.memmove.p0i8.p0i8.i64 67; CHECK-NEXT: store %S [[LOAD]], %S* %dst 68; CHECK-NEXT: ret void 69 %1 = load %S, %S* %src 70 %2 = load %S, %S* %src 71 store %S %1, %S* %dst 72 store %S %2, %S* %dst 73 ret void 74} 75 76; If the store address is computed ina complex manner, make 77; sure we lift the computation as well if needed and possible. 78define void @addrproducer(%S* %src, %S* %dst) { 79; CHECK-LABEL: addrproducer 80; CHECK: %dst2 = getelementptr %S, %S* %dst, i64 1 81; CHECK: call void @llvm.memmove.p0i8.p0i8.i64 82; CHECK-NEXT: store %S undef, %S* %dst 83; CHECK-NEXT: ret void 84 %1 = load %S, %S* %src 85 store %S undef, %S* %dst 86 %dst2 = getelementptr %S , %S* %dst, i64 1 87 store %S %1, %S* %dst2 88 ret void 89} 90 91define void @aliasaddrproducer(%S* %src, %S* %dst, i32* %dstidptr) { 92; CHECK-LABEL: aliasaddrproducer 93 %1 = load %S, %S* %src 94 store %S undef, %S* %dst 95 %dstindex = load i32, i32* %dstidptr 96 %dst2 = getelementptr %S , %S* %dst, i32 %dstindex 97 store %S %1, %S* %dst2 98 ret void 99} 100 101define void @noaliasaddrproducer(%S* %src, %S* noalias %dst, i32* noalias %dstidptr) { 102; CHECK-LABEL: noaliasaddrproducer 103 %1 = load %S, %S* %src 104 store %S undef, %S* %src 105 %2 = load i32, i32* %dstidptr 106 %dstindex = or i32 %2, 1 107 %dst2 = getelementptr %S , %S* %dst, i32 %dstindex 108 store %S %1, %S* %dst2 109 ret void 110} 111