1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -memcpyopt -dse -S -enable-memcpyopt-memoryssa=0 | FileCheck %s
3; RUN: opt < %s -basic-aa -memcpyopt -dse -S -enable-memcpyopt-memoryssa=1 -verify-memoryssa | FileCheck %s
4
5target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
6target triple = "i686-apple-darwin9"
7
8%0 = type { x86_fp80, x86_fp80 }
9%1 = type { i32, i32 }
10
11declare void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* nocapture, i8* nocapture, i64, i1) nounwind
12declare void @llvm.memcpy.p0i8.p1i8.i64(i8* nocapture, i8 addrspace(1)* nocapture, i64, i1) nounwind
13declare void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture, i64, i1) nounwind
14declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
15declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
16declare void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
17declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
18
19define void @test1(%0* sret(%0)  %agg.result, x86_fp80 %z.0, x86_fp80 %z.1) nounwind  {
20; CHECK-LABEL: @test1(
21; CHECK-NEXT:  entry:
22; CHECK-NEXT:    [[TMP2:%.*]] = alloca [[TMP0:%.*]], align 16
23; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [[TMP0]], align 16
24; CHECK-NEXT:    [[TMP5:%.*]] = fsub x86_fp80 0xK80000000000000000000, [[Z_1:%.*]]
25; CHECK-NEXT:    call void @ccoshl(%0* sret([[TMP0]]) [[TMP2]], x86_fp80 [[TMP5]], x86_fp80 [[Z_0:%.*]]) #[[ATTR0:[0-9]+]]
26; CHECK-NEXT:    [[TMP219:%.*]] = bitcast %0* [[TMP2]] to i8*
27; CHECK-NEXT:    [[MEMTMP20:%.*]] = bitcast %0* [[MEMTMP]] to i8*
28; CHECK-NEXT:    [[AGG_RESULT21:%.*]] = bitcast %0* [[AGG_RESULT:%.*]] to i8*
29; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[AGG_RESULT21]], i8* align 16 [[TMP219]], i32 32, i1 false)
30; CHECK-NEXT:    ret void
31;
32entry:
33  %tmp2 = alloca %0
34  %memtmp = alloca %0, align 16
35  %tmp5 = fsub x86_fp80 0xK80000000000000000000, %z.1
36  call void @ccoshl(%0* sret(%0) %memtmp, x86_fp80 %tmp5, x86_fp80 %z.0) nounwind
37  %tmp219 = bitcast %0* %tmp2 to i8*
38  %memtmp20 = bitcast %0* %memtmp to i8*
39  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %tmp219, i8* align 16 %memtmp20, i32 32, i1 false)
40  %agg.result21 = bitcast %0* %agg.result to i8*
41  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %agg.result21, i8* align 16 %tmp219, i32 32, i1 false)
42  ret void
43
44; Check that one of the memcpy's are removed.
45;; FIXME: PR 8643 We should be able to eliminate the last memcpy here.
46
47}
48
49declare void @ccoshl(%0* nocapture sret(%0), x86_fp80, x86_fp80) nounwind
50
51
52; The intermediate alloca and one of the memcpy's should be eliminated, the
53; other should be related with a memmove.
54define void @test2(i8* %P, i8* %Q) nounwind  {
55; CHECK-LABEL: @test2(
56; CHECK-NEXT:    call void @llvm.memmove.p0i8.p0i8.i32(i8* align 16 [[Q:%.*]], i8* align 16 [[P:%.*]], i32 32, i1 false)
57; CHECK-NEXT:    ret void
58;
59  %memtmp = alloca %0, align 16
60  %R = bitcast %0* %memtmp to i8*
61  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %R, i8* align 16 %P, i32 32, i1 false)
62  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %Q, i8* align 16 %R, i32 32, i1 false)
63  ret void
64
65}
66
67; The intermediate alloca and one of the memcpy's should be eliminated, the
68; other should be related with a memcpy.
69define void @test2_memcpy(i8* noalias %P, i8* noalias %Q) nounwind  {
70; CHECK-LABEL: @test2_memcpy(
71; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[Q:%.*]], i8* align 16 [[P:%.*]], i32 32, i1 false)
72; CHECK-NEXT:    ret void
73;
74  %memtmp = alloca %0, align 16
75  %R = bitcast %0* %memtmp to i8*
76  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %R, i8* align 16 %P, i32 32, i1 false)
77  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %Q, i8* align 16 %R, i32 32, i1 false)
78  ret void
79
80}
81
82; Same as @test2_memcpy, but the remaining memcpy should remain non-inline even
83; if the one eliminated was inline.
84define void @test3_memcpy(i8* noalias %P, i8* noalias %Q) nounwind  {
85; CHECK-LABEL: @test3_memcpy(
86; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[Q:%.*]], i8* align 16 [[P:%.*]], i32 32, i1 false)
87; CHECK-NEXT:    ret void
88;
89  %memtmp = alloca %0, align 16
90  %R = bitcast %0* %memtmp to i8*
91  call void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* align 16 %R, i8* align 16 %P, i32 32, i1 false)
92  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %Q, i8* align 16 %R, i32 32, i1 false)
93  ret void
94
95}
96
97; Same as @test2_memcpy, but the remaining memcpy should remain inline even
98; if the one eliminated was not inline.
99define void @test4_memcpy(i8* noalias %P, i8* noalias %Q) nounwind  {
100; CHECK-LABEL: @test4_memcpy(
101; CHECK-NEXT:    call void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* align 16 [[Q:%.*]], i8* align 16 [[P:%.*]], i32 32, i1 false)
102; CHECK-NEXT:    ret void
103;
104  %memtmp = alloca %0, align 16
105  %R = bitcast %0* %memtmp to i8*
106  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %R, i8* align 16 %P, i32 32, i1 false)
107  call void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* align 16 %Q, i8* align 16 %R, i32 32, i1 false)
108  ret void
109
110}
111
112; Same as @test2_memcpy, and the inline-ness should be preserved.
113define void @test5_memcpy(i8* noalias %P, i8* noalias %Q) nounwind  {
114; CHECK-LABEL: @test5_memcpy(
115; CHECK-NEXT:    call void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* align 16 [[Q:%.*]], i8* align 16 [[P:%.*]], i32 32, i1 false)
116; CHECK-NEXT:    ret void
117;
118  %memtmp = alloca %0, align 16
119  %R = bitcast %0* %memtmp to i8*
120  call void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* align 16 %R, i8* align 16 %P, i32 32, i1 false)
121  call void @llvm.memcpy.inline.p0i8.p0i8.i32(i8* align 16 %Q, i8* align 16 %R, i32 32, i1 false)
122  ret void
123
124}
125
126
127@x = external global %0
128
129define void @test3(%0* noalias sret(%0) %agg.result) nounwind  {
130; CHECK-LABEL: @test3(
131; CHECK-NEXT:    [[X_0:%.*]] = alloca [[TMP0:%.*]], align 16
132; CHECK-NEXT:    [[X_01:%.*]] = bitcast %0* [[X_0]] to i8*
133; CHECK-NEXT:    [[AGG_RESULT1:%.*]] = bitcast %0* [[AGG_RESULT:%.*]] to i8*
134; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[AGG_RESULT1]], i8* align 16 bitcast (%0* @x to i8*), i32 32, i1 false)
135; CHECK-NEXT:    [[AGG_RESULT2:%.*]] = bitcast %0* [[AGG_RESULT]] to i8*
136; CHECK-NEXT:    ret void
137;
138  %x.0 = alloca %0
139  %x.01 = bitcast %0* %x.0 to i8*
140  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %x.01, i8* align 16 bitcast (%0* @x to i8*), i32 32, i1 false)
141  %agg.result2 = bitcast %0* %agg.result to i8*
142  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %agg.result2, i8* align 16 %x.01, i32 32, i1 false)
143  ret void
144}
145
146
147; PR8644
148define void @test4(i8 *%P) {
149; CHECK-LABEL: @test4(
150; CHECK-NEXT:    call void @test4a(i8* byval(i8) align 1 [[P:%.*]])
151; CHECK-NEXT:    ret void
152;
153  %A = alloca %1
154  %a = bitcast %1* %A to i8*
155  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 %P, i64 8, i1 false)
156  call void @test4a(i8* align 1 byval(i8) %a)
157  ret void
158}
159
160; Make sure we don't remove the memcpy if the source address space doesn't match the byval argument
161define void @test4_addrspace(i8 addrspace(1)* %P) {
162; CHECK-LABEL: @test4_addrspace(
163; CHECK-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
164; CHECK-NEXT:    [[A2:%.*]] = bitcast %1* [[A1]] to i8*
165; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p1i8.i64(i8* align 4 [[A2]], i8 addrspace(1)* align 4 [[P:%.*]], i64 8, i1 false)
166; CHECK-NEXT:    call void @test4a(i8* byval(i8) align 1 [[A2]])
167; CHECK-NEXT:    ret void
168;
169  %a1 = alloca %1
170  %a2 = bitcast %1* %a1 to i8*
171  call void @llvm.memcpy.p0i8.p1i8.i64(i8* align 4 %a2, i8 addrspace(1)* align 4 %P, i64 8, i1 false)
172  call void @test4a(i8* align 1 byval(i8) %a2)
173  ret void
174}
175
176define void @test4_write_between(i8 *%P) {
177; CHECK-LABEL: @test4_write_between(
178; CHECK-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
179; CHECK-NEXT:    [[A2:%.*]] = bitcast %1* [[A1]] to i8*
180; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[A2]], i8* align 4 [[P:%.*]], i64 8, i1 false)
181; CHECK-NEXT:    store i8 0, i8* [[A2]], align 1
182; CHECK-NEXT:    call void @test4a(i8* byval(i8) align 1 [[A2]])
183; CHECK-NEXT:    ret void
184;
185  %a1 = alloca %1
186  %a2 = bitcast %1* %a1 to i8*
187  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a2, i8* align 4 %P, i64 8, i1 false)
188  store i8 0, i8* %a2
189  call void @test4a(i8* align 1 byval(i8) %a2)
190  ret void
191}
192
193define i8 @test4_read_between(i8 *%P) {
194; NO_MSSA-LABEL: @test4_read_between(
195; NO_MSSA-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
196; NO_MSSA-NEXT:    [[A2:%.*]] = bitcast %1* [[A1]] to i8*
197; NO_MSSA-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[A2]], i8* align 4 [[P:%.*]], i64 8, i1 false)
198; NO_MSSA-NEXT:    [[X:%.*]] = load i8, i8* [[A2]], align 1
199; NO_MSSA-NEXT:    call void @test4a(i8* byval align 1 [[A2]])
200; NO_MSSA-NEXT:    ret i8 [[X]]
201;
202; MSSA-LABEL: @test4_read_between(
203; MSSA-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
204; MSSA-NEXT:    [[A2:%.*]] = bitcast %1* [[A1]] to i8*
205; MSSA-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[A2]], i8* align 4 [[P:%.*]], i64 8, i1 false)
206; MSSA-NEXT:    [[X:%.*]] = load i8, i8* [[A2]], align 1
207; MSSA-NEXT:    call void @test4a(i8* byval align 1 [[P]])
208; MSSA-NEXT:    ret i8 [[X]]
209;
210  %a1 = alloca %1
211  %a2 = bitcast %1* %a1 to i8*
212  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a2, i8* align 4 %P, i64 8, i1 false)
213  %x = load i8, i8* %a2
214  call void @test4a(i8* align 1 byval(i8) %a2)
215  ret i8 %x
216}
217
218define void @test4_non_local(i8 *%P, i1 %c) {
219; NO_MSSA-LABEL: @test4_non_local(
220; NO_MSSA-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
221; NO_MSSA-NEXT:    [[A2:%.*]] = bitcast %1* [[A1]] to i8*
222; NO_MSSA-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[A2]], i8* align 4 [[P:%.*]], i64 8, i1 false)
223; NO_MSSA-NEXT:    br i1 [[C:%.*]], label [[CALL:%.*]], label [[EXIT:%.*]]
224; NO_MSSA:       call:
225; NO_MSSA-NEXT:    call void @test4a(i8* byval align 1 [[A2]])
226; NO_MSSA-NEXT:    br label [[EXIT]]
227; NO_MSSA:       exit:
228; NO_MSSA-NEXT:    ret void
229;
230; MSSA-LABEL: @test4_non_local(
231; MSSA-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
232; MSSA-NEXT:    [[A2:%.*]] = bitcast %1* [[A1]] to i8*
233; MSSA-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[A2]], i8* align 4 [[P:%.*]], i64 8, i1 false)
234; MSSA-NEXT:    br i1 [[C:%.*]], label [[CALL:%.*]], label [[EXIT:%.*]]
235; MSSA:       call:
236; MSSA-NEXT:    call void @test4a(i8* byval align 1 [[P]])
237; MSSA-NEXT:    br label [[EXIT]]
238; MSSA:       exit:
239; MSSA-NEXT:    ret void
240;
241  %a1 = alloca %1
242  %a2 = bitcast %1* %a1 to i8*
243  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a2, i8* align 4 %P, i64 8, i1 false)
244  br i1 %c, label %call, label %exit
245
246call:
247  call void @test4a(i8* align 1 byval(i8) %a2)
248  br label %exit
249
250exit:
251  ret void
252}
253
254declare void @test4a(i8* align 1 byval(i8))
255
256%struct.S = type { i128, [4 x i8]}
257
258@sS = external global %struct.S, align 16
259
260declare void @test5a(%struct.S* align 16 byval(%struct.S)) nounwind ssp
261
262
263; rdar://8713376 - This memcpy can't be eliminated.
264define i32 @test5(i32 %x) nounwind ssp {
265; CHECK-LABEL: @test5(
266; CHECK-NEXT:  entry:
267; CHECK-NEXT:    [[Y:%.*]] = alloca [[STRUCT_S:%.*]], align 16
268; CHECK-NEXT:    [[TMP:%.*]] = bitcast %struct.S* [[Y]] to i8*
269; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP]], i8* align 16 bitcast (%struct.S* @sS to i8*), i64 32, i1 false)
270; CHECK-NEXT:    [[A:%.*]] = getelementptr [[STRUCT_S]], %struct.S* [[Y]], i64 0, i32 1, i64 0
271; CHECK-NEXT:    store i8 4, i8* [[A]], align 1
272; CHECK-NEXT:    call void @test5a(%struct.S* byval([[STRUCT_S]]) align 16 [[Y]])
273; CHECK-NEXT:    ret i32 0
274;
275entry:
276  %y = alloca %struct.S, align 16
277  %tmp = bitcast %struct.S* %y to i8*
278  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %tmp, i8* align 16 bitcast (%struct.S* @sS to i8*), i64 32, i1 false)
279  %a = getelementptr %struct.S, %struct.S* %y, i64 0, i32 1, i64 0
280  store i8 4, i8* %a
281  call void @test5a(%struct.S* align 16 byval(%struct.S) %y)
282  ret i32 0
283}
284
285;; Noop memcpy should be zapped.
286define void @test6(i8 *%P) {
287; CHECK-LABEL: @test6(
288; CHECK-NEXT:    ret void
289;
290  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %P, i8* align 4 %P, i64 8, i1 false)
291  ret void
292}
293
294
295; PR9794 - Should forward memcpy into byval argument even though the memcpy
296; isn't itself 8 byte aligned.
297%struct.p = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }
298
299define i32 @test7(%struct.p* nocapture align 8 byval(%struct.p) %q) nounwind ssp {
300; CHECK-LABEL: @test7(
301; CHECK-NEXT:  entry:
302; CHECK-NEXT:    [[CALL:%.*]] = call i32 @g(%struct.p* byval([[STRUCT_P:%.*]]) align 8 [[Q:%.*]]) #[[ATTR0]]
303; CHECK-NEXT:    ret i32 [[CALL]]
304;
305entry:
306  %agg.tmp = alloca %struct.p, align 4
307  %tmp = bitcast %struct.p* %agg.tmp to i8*
308  %tmp1 = bitcast %struct.p* %q to i8*
309  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %tmp, i8* align 4 %tmp1, i64 48, i1 false)
310  %call = call i32 @g(%struct.p* align 8 byval(%struct.p) %agg.tmp) nounwind
311  ret i32 %call
312}
313
314declare i32 @g(%struct.p* align 8 byval(%struct.p))
315
316
317; PR11142 - When looking for a memcpy-memcpy dependency, don't get stuck on
318; instructions between the memcpy's that only affect the destination pointer.
319@test8.str = internal constant [7 x i8] c"ABCDEF\00"
320
321define void @test8() {
322; CHECK-LABEL: @test8(
323; CHECK-NEXT:    ret void
324;
325  %A = tail call i8* @malloc(i32 10)
326  %B = getelementptr inbounds i8, i8* %A, i64 2
327  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %B, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @test8.str, i64 0, i64 0), i32 7, i1 false)
328  %C = tail call i8* @malloc(i32 10)
329  %D = getelementptr inbounds i8, i8* %C, i64 2
330  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %D, i8* %B, i32 7, i1 false)
331  ret void
332}
333
334declare noalias i8* @malloc(i32) willreturn
335
336; rdar://11341081
337%struct.big = type { [50 x i32] }
338
339define void @test9_addrspacecast() nounwind ssp uwtable {
340; CHECK-LABEL: @test9_addrspacecast(
341; CHECK-NEXT:  entry:
342; CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4
343; CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4
344; CHECK-NEXT:    call void @f1(%struct.big* sret([[STRUCT_BIG]]) [[B]])
345; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast %struct.big* [[B]] to i8 addrspace(1)*
346; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast %struct.big* [[TMP]] to i8 addrspace(1)*
347; CHECK-NEXT:    call void @f2(%struct.big* [[B]])
348; CHECK-NEXT:    ret void
349;
350entry:
351  %b = alloca %struct.big, align 4
352  %tmp = alloca %struct.big, align 4
353  call void @f1(%struct.big* sret(%struct.big) %tmp)
354  %0 = addrspacecast %struct.big* %b to i8 addrspace(1)*
355  %1 = addrspacecast %struct.big* %tmp to i8 addrspace(1)*
356  call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 %0, i8 addrspace(1)* align 4 %1, i64 200, i1 false)
357  call void @f2(%struct.big* %b)
358  ret void
359}
360
361define void @test9() nounwind ssp uwtable {
362; CHECK-LABEL: @test9(
363; CHECK-NEXT:  entry:
364; CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4
365; CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4
366; CHECK-NEXT:    call void @f1(%struct.big* sret([[STRUCT_BIG]]) [[B]])
367; CHECK-NEXT:    [[TMP0:%.*]] = bitcast %struct.big* [[B]] to i8*
368; CHECK-NEXT:    [[TMP1:%.*]] = bitcast %struct.big* [[TMP]] to i8*
369; CHECK-NEXT:    call void @f2(%struct.big* [[B]])
370; CHECK-NEXT:    ret void
371;
372entry:
373  %b = alloca %struct.big, align 4
374  %tmp = alloca %struct.big, align 4
375  call void @f1(%struct.big* sret(%struct.big) %tmp)
376  %0 = bitcast %struct.big* %b to i8*
377  %1 = bitcast %struct.big* %tmp to i8*
378  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 200, i1 false)
379  call void @f2(%struct.big* %b)
380  ret void
381}
382
383; rdar://14073661.
384; Test10 triggered assertion when the compiler try to get the size of the
385; opaque type of *x, where the x is the formal argument with attribute 'sret'.
386
387%opaque = type opaque
388declare void @foo(i32* noalias nocapture)
389
390define void @test10(%opaque* noalias nocapture sret(%opaque) %x, i32 %y) {
391; CHECK-LABEL: @test10(
392; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
393; CHECK-NEXT:    store i32 [[Y:%.*]], i32* [[A]], align 4
394; CHECK-NEXT:    call void @foo(i32* noalias nocapture [[A]])
395; CHECK-NEXT:    [[C:%.*]] = load i32, i32* [[A]], align 4
396; CHECK-NEXT:    [[D:%.*]] = bitcast %opaque* [[X:%.*]] to i32*
397; CHECK-NEXT:    store i32 [[C]], i32* [[D]], align 4
398; CHECK-NEXT:    ret void
399;
400  %a = alloca i32, align 4
401  store i32 %y, i32* %a
402  call void @foo(i32* noalias nocapture %a)
403  %c = load i32, i32* %a
404  %d = bitcast %opaque* %x to i32*
405  store i32 %c, i32* %d
406  ret void
407}
408
409; don't create new addressspacecasts when we don't know they're safe for the target
410define void @test11([20 x i32] addrspace(1)* nocapture dereferenceable(80) %P) {
411; CHECK-LABEL: @test11(
412; CHECK-NEXT:    [[B:%.*]] = bitcast [20 x i32] addrspace(1)* [[P:%.*]] to i8 addrspace(1)*
413; CHECK-NEXT:    call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 [[B]], i8 0, i64 80, i1 false)
414; CHECK-NEXT:    ret void
415;
416  %A = alloca [20 x i32], align 4
417  %a = bitcast [20 x i32]* %A to i8*
418  %b = bitcast [20 x i32] addrspace(1)* %P to i8 addrspace(1)*
419  call void @llvm.memset.p0i8.i64(i8* align 4 %a, i8 0, i64 80, i1 false)
420  call void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* align 4 %b, i8* align 4 %a, i64 80, i1 false)
421  ret void
422}
423
424declare void @f1(%struct.big* nocapture sret(%struct.big))
425declare void @f2(%struct.big*)
426