[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / MemCpyOpt / callslot.ll
blobc118646669ea42cf5fe29e5c45a819ccfdc86dc5
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -memcpyopt < %s -verify-memoryssa | FileCheck %s
4 define i8 @read_dest_between_call_and_memcpy() {
5 ; CHECK-LABEL: @read_dest_between_call_and_memcpy(
6 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
7 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
8 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
9 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
10 ; CHECK-NEXT:    store i8 1, i8* [[DEST_I8]], align 1
11 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[SRC_I8]], i8 0, i64 16, i1 false)
12 ; CHECK-NEXT:    [[X:%.*]] = load i8, i8* [[DEST_I8]], align 1
13 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[DEST_I8]], i8 0, i64 16, i1 false)
14 ; CHECK-NEXT:    ret i8 [[X]]
16   %dest = alloca [16 x i8]
17   %src = alloca [16 x i8]
18   %dest.i8 = bitcast [16 x i8]* %dest to i8*
19   %src.i8 = bitcast [16 x i8]* %src to i8*
20   store i8 1, i8* %dest.i8
21   call void @llvm.memset.p0i8.i64(i8* %src.i8, i8 0, i64 16, i1 false)
22   %x = load i8, i8* %dest.i8
23   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
24   ret i8 %x
27 define i8 @read_src_between_call_and_memcpy() {
28 ; CHECK-LABEL: @read_src_between_call_and_memcpy(
29 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
30 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
31 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
32 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
33 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[SRC_I8]], i8 0, i64 16, i1 false)
34 ; CHECK-NEXT:    [[X:%.*]] = load i8, i8* [[SRC_I8]], align 1
35 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[DEST_I8]], i8 0, i64 16, i1 false)
36 ; CHECK-NEXT:    ret i8 [[X]]
38   %dest = alloca [16 x i8]
39   %src = alloca [16 x i8]
40   %dest.i8 = bitcast [16 x i8]* %dest to i8*
41   %src.i8 = bitcast [16 x i8]* %src to i8*
42   call void @llvm.memset.p0i8.i64(i8* %src.i8, i8 0, i64 16, i1 false)
43   %x = load i8, i8* %src.i8
44   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
45   ret i8 %x
48 define void @write_dest_between_call_and_memcpy() {
49 ; CHECK-LABEL: @write_dest_between_call_and_memcpy(
50 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
51 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
52 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
53 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
54 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[SRC_I8]], i8 0, i64 16, i1 false)
55 ; CHECK-NEXT:    store i8 1, i8* [[DEST_I8]], align 1
56 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[DEST_I8]], i8 0, i64 16, i1 false)
57 ; CHECK-NEXT:    ret void
59   %dest = alloca [16 x i8]
60   %src = alloca [16 x i8]
61   %dest.i8 = bitcast [16 x i8]* %dest to i8*
62   %src.i8 = bitcast [16 x i8]* %src to i8*
63   call void @llvm.memset.p0i8.i64(i8* %src.i8, i8 0, i64 16, i1 false)
64   store i8 1, i8* %dest.i8
65   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
66   ret void
69 define void @write_src_between_call_and_memcpy() {
70 ; CHECK-LABEL: @write_src_between_call_and_memcpy(
71 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
72 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
73 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
74 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
75 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[SRC_I8]], i8 0, i64 16, i1 false)
76 ; CHECK-NEXT:    store i8 1, i8* [[SRC_I8]], align 1
77 ; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST_I8]], i8* [[SRC_I8]], i64 16, i1 false)
78 ; CHECK-NEXT:    ret void
80   %dest = alloca [16 x i8]
81   %src = alloca [16 x i8]
82   %dest.i8 = bitcast [16 x i8]* %dest to i8*
83   %src.i8 = bitcast [16 x i8]* %src to i8*
84   call void @llvm.memset.p0i8.i64(i8* %src.i8, i8 0, i64 16, i1 false)
85   store i8 1, i8* %src.i8
86   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
87   ret void
90 define void @throw_between_call_and_mempy(i8* dereferenceable(16) %dest.i8) {
91 ; CHECK-LABEL: @throw_between_call_and_mempy(
92 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
93 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
94 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[SRC_I8]], i8 0, i64 16, i1 false)
95 ; CHECK-NEXT:    call void @may_throw() #[[ATTR2:[0-9]+]]
96 ; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[DEST_I8:%.*]], i8 0, i64 16, i1 false)
97 ; CHECK-NEXT:    ret void
99   %src = alloca [16 x i8]
100   %src.i8 = bitcast [16 x i8]* %src to i8*
101   call void @llvm.memset.p0i8.i64(i8* %src.i8, i8 0, i64 16, i1 false)
102   call void @may_throw() readnone
103   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
104   ret void
107 define void @dest_is_gep_nounwind_call() {
108 ; CHECK-LABEL: @dest_is_gep_nounwind_call(
109 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
110 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [8 x i8], align 1
111 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [8 x i8]* [[SRC]] to i8*
112 ; CHECK-NEXT:    [[DEST_I8:%.*]] = getelementptr [16 x i8], [16 x i8]* [[DEST]], i64 0, i64 8
113 ; CHECK-NEXT:    [[DEST_I81:%.*]] = bitcast i8* [[DEST_I8]] to [8 x i8]*
114 ; CHECK-NEXT:    [[DEST_I812:%.*]] = bitcast [8 x i8]* [[DEST_I81]] to i8*
115 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I812]]) #[[ATTR3:[0-9]+]]
116 ; CHECK-NEXT:    ret void
118   %dest = alloca [16 x i8]
119   %src = alloca [8 x i8]
120   %src.i8 = bitcast [8 x i8]* %src to i8*
121   %dest.i8 = getelementptr [16 x i8], [16 x i8]* %dest, i64 0, i64 8
122   call void @accept_ptr(i8* %src.i8) nounwind
123   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 8, i1 false)
124   ret void
127 define void @dest_is_gep_may_throw_call() {
128 ; CHECK-LABEL: @dest_is_gep_may_throw_call(
129 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
130 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [8 x i8], align 1
131 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [8 x i8]* [[SRC]] to i8*
132 ; CHECK-NEXT:    [[DEST_I8:%.*]] = getelementptr [16 x i8], [16 x i8]* [[DEST]], i64 0, i64 8
133 ; CHECK-NEXT:    [[DEST_I81:%.*]] = bitcast i8* [[DEST_I8]] to [8 x i8]*
134 ; CHECK-NEXT:    [[DEST_I812:%.*]] = bitcast [8 x i8]* [[DEST_I81]] to i8*
135 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I812]])
136 ; CHECK-NEXT:    ret void
138   %dest = alloca [16 x i8]
139   %src = alloca [8 x i8]
140   %src.i8 = bitcast [8 x i8]* %src to i8*
141   %dest.i8 = getelementptr [16 x i8], [16 x i8]* %dest, i64 0, i64 8
142   call void @accept_ptr(i8* %src.i8)
143   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 8, i1 false)
144   ret void
147 define void @dest_is_gep_requires_movement() {
148 ; CHECK-LABEL: @dest_is_gep_requires_movement(
149 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
150 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [8 x i8], align 1
151 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [8 x i8]* [[SRC]] to i8*
152 ; CHECK-NEXT:    [[DEST_I8:%.*]] = getelementptr [16 x i8], [16 x i8]* [[DEST]], i64 0, i64 8
153 ; CHECK-NEXT:    [[DEST_I81:%.*]] = bitcast i8* [[DEST_I8]] to [8 x i8]*
154 ; CHECK-NEXT:    [[DEST_I812:%.*]] = bitcast [8 x i8]* [[DEST_I81]] to i8*
155 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I812]]) #[[ATTR3]]
156 ; CHECK-NEXT:    ret void
158   %dest = alloca [16 x i8]
159   %src = alloca [8 x i8]
160   %src.i8 = bitcast [8 x i8]* %src to i8*
161   call void @accept_ptr(i8* %src.i8) nounwind
162   %dest.i8 = getelementptr [16 x i8], [16 x i8]* %dest, i64 0, i64 8
163   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 8, i1 false)
164   ret void
167 define void @capture_before_call_argmemonly() {
168 ; CHECK-LABEL: @capture_before_call_argmemonly(
169 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
170 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
171 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
172 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
173 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I8]])
174 ; CHECK-NEXT:    [[DEST1:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
175 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST1]]) #[[ATTR4:[0-9]+]]
176 ; CHECK-NEXT:    ret void
178   %dest = alloca [16 x i8]
179   %src = alloca [16 x i8]
180   %dest.i8 = bitcast [16 x i8]* %dest to i8*
181   %src.i8 = bitcast [16 x i8]* %src to i8*
182   call void @accept_ptr(i8* %dest.i8) ; capture
183   call void @accept_ptr(i8* %src.i8) argmemonly
184   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
185   ret void
188 define void @capture_before_call_argmemonly_nounwind() {
189 ; CHECK-LABEL: @capture_before_call_argmemonly_nounwind(
190 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
191 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
192 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
193 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
194 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I8]])
195 ; CHECK-NEXT:    [[DEST1:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
196 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST1]]) #[[ATTR5:[0-9]+]]
197 ; CHECK-NEXT:    ret void
199   %dest = alloca [16 x i8]
200   %src = alloca [16 x i8]
201   %dest.i8 = bitcast [16 x i8]* %dest to i8*
202   %src.i8 = bitcast [16 x i8]* %src to i8*
203   call void @accept_ptr(i8* %dest.i8) ; capture
204   ; NB: argmemonly currently implies willreturn.
205   call void @accept_ptr(i8* %src.i8) argmemonly nounwind
206   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
207   ret void
210 define void @capture_before_call_argmemonly_nounwind_willreturn() {
211 ; CHECK-LABEL: @capture_before_call_argmemonly_nounwind_willreturn(
212 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
213 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
214 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
215 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
216 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I8]])
217 ; CHECK-NEXT:    [[DEST1:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
218 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST1]]) #[[ATTR6:[0-9]+]]
219 ; CHECK-NEXT:    ret void
221   %dest = alloca [16 x i8]
222   %src = alloca [16 x i8]
223   %dest.i8 = bitcast [16 x i8]* %dest to i8*
224   %src.i8 = bitcast [16 x i8]* %src to i8*
225   call void @accept_ptr(i8* %dest.i8) ; capture
226   call void @accept_ptr(i8* %src.i8) argmemonly nounwind willreturn
227   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
228   ret void
231 ; There is no path from the capture back to the memcpy.
232 ; So we are allowed to perform the call slot optimization.
233 define void @capture_nopath_call(i1 %cond) {
234 ; CHECK-LABEL: @capture_nopath_call(
235 ; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1
236 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1
237 ; CHECK-NEXT:    [[DEST_I8:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
238 ; CHECK-NEXT:    [[SRC_I8:%.*]] = bitcast [16 x i8]* [[SRC]] to i8*
239 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[CAPTURES:%.*]], label [[NOCAPTURES:%.*]]
240 ; CHECK:       captures:
241 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST_I8]])
242 ; CHECK-NEXT:    ret void
243 ; CHECK:       nocaptures:
244 ; CHECK-NEXT:    [[DEST1:%.*]] = bitcast [16 x i8]* [[DEST]] to i8*
245 ; CHECK-NEXT:    call void @accept_ptr(i8* [[DEST1]]) #[[ATTR3]]
246 ; CHECK-NEXT:    ret void
248   %dest = alloca [16 x i8]
249   %src = alloca [16 x i8]
250   %dest.i8 = bitcast [16 x i8]* %dest to i8*
251   %src.i8 = bitcast [16 x i8]* %src to i8*
252   br i1 %cond, label %captures, label %nocaptures
254 captures:
255   call void @accept_ptr(i8* %dest.i8) ; capture
256   ret void
258 nocaptures:
259   call void @accept_ptr(i8* %src.i8) nounwind
260   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest.i8, i8* %src.i8, i64 16, i1 false)
261   ret void
264 declare void @may_throw()
265 declare void @accept_ptr(i8*)
266 declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)
267 declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1)