1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -memcpyopt -S < %s -verify-memoryssa | FileCheck %s 3 4target datalayout = "e-i64:64-f80:128-n8:16:32:64" 5target triple = "x86_64-unknown-linux-gnu" 6 7%S = type { i8*, i8, i32 } 8 9define void @copy(%S* %src, %S* %dst) { 10; CHECK-LABEL: @copy( 11; CHECK-NEXT: [[TMP1:%.*]] = bitcast %S* [[DST:%.*]] to i8* 12; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[SRC:%.*]] to i8* 13; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i64 16, i1 false) 14; CHECK-NEXT: ret void 15; 16 %1 = load %S, %S* %src 17 store %S %1, %S* %dst 18 ret void 19} 20 21define void @noaliassrc(%S* noalias %src, %S* %dst) { 22; CHECK-LABEL: @noaliassrc( 23; CHECK-NEXT: [[TMP1:%.*]] = bitcast %S* [[DST:%.*]] to i8* 24; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[SRC:%.*]] to i8* 25; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i64 16, i1 false) 26; CHECK-NEXT: ret void 27; 28 %1 = load %S, %S* %src 29 store %S %1, %S* %dst 30 ret void 31} 32 33define void @noaliasdst(%S* %src, %S* noalias %dst) { 34; CHECK-LABEL: @noaliasdst( 35; CHECK-NEXT: [[TMP1:%.*]] = bitcast %S* [[DST:%.*]] to i8* 36; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[SRC:%.*]] to i8* 37; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i64 16, i1 false) 38; CHECK-NEXT: ret void 39; 40 %1 = load %S, %S* %src 41 store %S %1, %S* %dst 42 ret void 43} 44 45define void @destroysrc(%S* %src, %S* %dst) { 46; CHECK-LABEL: @destroysrc( 47; CHECK-NEXT: [[TMP1:%.*]] = load [[S:%.*]], %S* [[SRC:%.*]], align 8 48; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[SRC]] to i8* 49; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP2]], i8 0, i64 16, i1 false) 50; CHECK-NEXT: store [[S]] [[TMP1]], %S* [[DST:%.*]], align 8 51; CHECK-NEXT: ret void 52; 53 %1 = load %S, %S* %src 54 store %S zeroinitializer, %S* %src 55 store %S %1, %S* %dst 56 ret void 57} 58 59define void @destroynoaliassrc(%S* noalias %src, %S* %dst) { 60; CHECK-LABEL: @destroynoaliassrc( 61; CHECK-NEXT: [[TMP1:%.*]] = bitcast %S* [[SRC:%.*]] to i8* 62; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[DST:%.*]] to i8* 63; CHECK-NEXT: [[TMP3:%.*]] = bitcast %S* [[SRC]] to i8* 64; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 16, i1 false) 65; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP1]], i8 0, i64 16, i1 false) 66; CHECK-NEXT: ret void 67; 68 %1 = load %S, %S* %src 69 store %S zeroinitializer, %S* %src 70 store %S %1, %S* %dst 71 ret void 72} 73 74define void @copyalias(%S* %src, %S* %dst) { 75; CHECK-LABEL: @copyalias( 76; CHECK-NEXT: [[TMP1:%.*]] = load [[S:%.*]], %S* [[SRC:%.*]], align 8 77; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[DST:%.*]] to i8* 78; CHECK-NEXT: [[TMP3:%.*]] = bitcast %S* [[SRC]] to i8* 79; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 16, i1 false) 80; CHECK-NEXT: store [[S]] [[TMP1]], %S* [[DST]], align 8 81; CHECK-NEXT: ret void 82; 83 %1 = load %S, %S* %src 84 %2 = load %S, %S* %src 85 store %S %1, %S* %dst 86 store %S %2, %S* %dst 87 ret void 88} 89 90; If the store address is computed in a complex manner, make 91; sure we lift the computation as well if needed and possible. 92define void @addrproducer(%S* %src, %S* %dst) { 93; CHECK-LABEL: @addrproducer( 94; CHECK-NEXT: [[TMP1:%.*]] = bitcast %S* [[DST:%.*]] to i8* 95; CHECK-NEXT: [[DST2:%.*]] = getelementptr [[S:%.*]], %S* [[DST]], i64 1 96; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[DST2]] to i8* 97; CHECK-NEXT: [[TMP3:%.*]] = bitcast %S* [[SRC:%.*]] to i8* 98; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 16, i1 false) 99; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP1]], i8 undef, i64 16, i1 false) 100; CHECK-NEXT: ret void 101; 102 %1 = load %S, %S* %src 103 store %S undef, %S* %dst 104 %dst2 = getelementptr %S , %S* %dst, i64 1 105 store %S %1, %S* %dst2 106 ret void 107} 108 109define void @aliasaddrproducer(%S* %src, %S* %dst, i32* %dstidptr) { 110; CHECK-LABEL: @aliasaddrproducer( 111; CHECK-NEXT: [[TMP1:%.*]] = load [[S:%.*]], %S* [[SRC:%.*]], align 8 112; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[DST:%.*]] to i8* 113; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP2]], i8 undef, i64 16, i1 false) 114; CHECK-NEXT: [[DSTINDEX:%.*]] = load i32, i32* [[DSTIDPTR:%.*]], align 4 115; CHECK-NEXT: [[DST2:%.*]] = getelementptr [[S]], %S* [[DST]], i32 [[DSTINDEX]] 116; CHECK-NEXT: store [[S]] [[TMP1]], %S* [[DST2]], align 8 117; CHECK-NEXT: ret void 118; 119 %1 = load %S, %S* %src 120 store %S undef, %S* %dst 121 %dstindex = load i32, i32* %dstidptr 122 %dst2 = getelementptr %S , %S* %dst, i32 %dstindex 123 store %S %1, %S* %dst2 124 ret void 125} 126 127define void @noaliasaddrproducer(%S* %src, %S* noalias %dst, i32* noalias %dstidptr) { 128; CHECK-LABEL: @noaliasaddrproducer( 129; CHECK-NEXT: [[TMP1:%.*]] = bitcast %S* [[SRC:%.*]] to i8* 130; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[DSTIDPTR:%.*]], align 4 131; CHECK-NEXT: [[DSTINDEX:%.*]] = or i32 [[TMP2]], 1 132; CHECK-NEXT: [[DST2:%.*]] = getelementptr [[S:%.*]], %S* [[DST:%.*]], i32 [[DSTINDEX]] 133; CHECK-NEXT: [[TMP3:%.*]] = bitcast %S* [[DST2]] to i8* 134; CHECK-NEXT: [[TMP4:%.*]] = bitcast %S* [[SRC]] to i8* 135; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) 136; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP1]], i8 undef, i64 16, i1 false) 137; CHECK-NEXT: ret void 138; 139 %1 = load %S, %S* %src 140 store %S undef, %S* %src 141 %2 = load i32, i32* %dstidptr 142 %dstindex = or i32 %2, 1 143 %dst2 = getelementptr %S , %S* %dst, i32 %dstindex 144 store %S %1, %S* %dst2 145 ret void 146} 147 148define void @throwing_call(%S* noalias %src, %S* %dst) { 149; CHECK-LABEL: @throwing_call( 150; CHECK-NEXT: [[TMP1:%.*]] = load [[S:%.*]], %S* [[SRC:%.*]], align 8 151; CHECK-NEXT: [[TMP2:%.*]] = bitcast %S* [[SRC]] to i8* 152; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP2]], i8 0, i64 16, i1 false) 153; CHECK-NEXT: call void @call() [[ATTR2:#.*]] 154; CHECK-NEXT: store [[S]] [[TMP1]], %S* [[DST:%.*]], align 8 155; CHECK-NEXT: ret void 156; 157 %1 = load %S, %S* %src 158 store %S zeroinitializer, %S* %src 159 call void @call() readnone 160 store %S %1, %S* %dst 161 ret void 162} 163 164declare void @call() 165