[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / MemCpyOpt / fca2memcpy.ll
blobf18d6cd2cecb1b2e76c46a8b9e30fcb69a1e754c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -memcpyopt -S < %s -verify-memoryssa | FileCheck %s
4 target datalayout = "e-i64:64-f80:128-n8:16:32:64"
5 target triple = "x86_64-unknown-linux-gnu"
7 %S = type { i8*, i8, i32 }
9 define 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
16   %1 = load %S, %S* %src
17   store %S %1, %S* %dst
18   ret void
21 define 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
28   %1 = load %S, %S* %src
29   store %S %1, %S* %dst
30   ret void
33 define 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
40   %1 = load %S, %S* %src
41   store %S %1, %S* %dst
42   ret void
45 define 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
53   %1 = load %S, %S* %src
54   store %S zeroinitializer, %S* %src
55   store %S %1, %S* %dst
56   ret void
59 define 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
68   %1 = load %S, %S* %src
69   store %S zeroinitializer, %S* %src
70   store %S %1, %S* %dst
71   ret void
74 define 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
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
90 ; If the store address is computed in a complex manner, make
91 ; sure we lift the computation as well if needed and possible.
92 define 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
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
109 define 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
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
127 define 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
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
148 define 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
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
164 declare void @call()