1 ; RUN: opt -memcpyopt -S < %s | FileCheck %s 2 3 target datalayout = "e-i64:64-f80:128-n8:16:32:64" 4 target triple = "x86_64-unknown-linux-gnu" 5 6 %S = type { i8*, i8, i32 } 7 8 define 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 18 define 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 28 define 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 38 define 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 50 define 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 62 define 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. 78 define 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 91 define 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 101 define 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