xref: /llvm-project/llvm/test/Transforms/DeadStoreElimination/simple.ll (revision 1ca64c5fb74270661ca2f9ebd821f47dcb3152b4)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=dse -S | FileCheck %s
3; RUN: opt < %s -aa-pipeline=basic-aa -passes=dse -S | FileCheck %s
4target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
5
6declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
7declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture, i8, i64, i32) nounwind
8declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
9declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i32) nounwind
10declare void @llvm.init.trampoline(ptr, ptr, ptr)
11declare void @llvm.matrix.column.major.store(<6 x float>, ptr, i64, i1, i32, i32)
12
13define void @test1(ptr %Q, ptr %P) {
14; CHECK-LABEL: @test1(
15; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
16; CHECK-NEXT:    ret void
17;
18  %DEAD = load i32, ptr %Q
19  store i32 %DEAD, ptr %P
20  store i32 0, ptr %P
21  ret void
22}
23
24; PR8677
25@g = global i32 1
26
27define i32 @test3(ptr %g_addr) nounwind {
28; CHECK-LABEL: @test3(
29; CHECK-NEXT:    [[G_VALUE:%.*]] = load i32, ptr [[G_ADDR:%.*]], align 4
30; CHECK-NEXT:    store i32 -1, ptr @g, align 4
31; CHECK-NEXT:    store i32 [[G_VALUE]], ptr [[G_ADDR]], align 4
32; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr @g, align 4
33; CHECK-NEXT:    ret i32 [[TMP3]]
34;
35  %g_value = load i32, ptr %g_addr, align 4
36  store i32 -1, ptr @g, align 4
37  store i32 %g_value, ptr %g_addr, align 4
38  %tmp3 = load i32, ptr @g, align 4
39  ret i32 %tmp3
40}
41
42
43define void @test4(ptr %Q) {
44; CHECK-LABEL: @test4(
45; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[Q:%.*]], align 4
46; CHECK-NEXT:    store volatile i32 [[A]], ptr [[Q]], align 4
47; CHECK-NEXT:    ret void
48;
49  %a = load i32, ptr %Q
50  store volatile i32 %a, ptr %Q
51  ret void
52}
53
54; PR8576 - Should delete store of 10 even though p/q are may aliases.
55define void @test2(ptr %p, ptr %q) {
56; CHECK-LABEL: @test2(
57; CHECK-NEXT:    store i32 20, ptr [[Q:%.*]], align 4
58; CHECK-NEXT:    store i32 30, ptr [[P:%.*]], align 4
59; CHECK-NEXT:    ret void
60;
61  store i32 10, ptr %p, align 4
62  store i32 20, ptr %q, align 4
63  store i32 30, ptr %p, align 4
64  ret void
65}
66
67; Should delete store of 10 even though memset is a may-store to P (P and Q may
68; alias).
69define void @test6(ptr %p, ptr %q) {
70; CHECK-LABEL: @test6(
71; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[Q:%.*]], i8 42, i64 900, i1 false)
72; CHECK-NEXT:    store i32 30, ptr [[P:%.*]], align 4
73; CHECK-NEXT:    ret void
74;
75  store i32 10, ptr %p, align 4       ;; dead.
76  call void @llvm.memset.p0.i64(ptr %q, i8 42, i64 900, i1 false)
77  store i32 30, ptr %p, align 4
78  ret void
79}
80
81; Should delete store of 10 even though memset is a may-store to P (P and Q may
82; alias).
83define void @test6_atomic(ptr align 4 %p, ptr align 4 %q) {
84; CHECK-LABEL: @test6_atomic(
85; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[Q:%.*]], i8 42, i64 900, i32 4)
86; CHECK-NEXT:    store atomic i32 30, ptr [[P:%.*]] unordered, align 4
87; CHECK-NEXT:    ret void
88;
89  store atomic i32 10, ptr %p unordered, align 4       ;; dead.
90  call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %q, i8 42, i64 900, i32 4)
91  store atomic i32 30, ptr %p unordered, align 4
92  ret void
93}
94
95; Should delete store of 10 even though memcpy is a may-store to P (P and Q may
96; alias).
97define void @test7(ptr %p, ptr %q, ptr noalias %r) {
98; CHECK-LABEL: @test7(
99; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[Q:%.*]], ptr [[R:%.*]], i64 900, i1 false)
100; CHECK-NEXT:    store i32 30, ptr [[P:%.*]], align 4
101; CHECK-NEXT:    ret void
102;
103  store i32 10, ptr %p, align 4       ;; dead.
104  call void @llvm.memcpy.p0.p0.i64(ptr %q, ptr %r, i64 900, i1 false)
105  store i32 30, ptr %p, align 4
106  ret void
107}
108
109; Should delete store of 10 even though memcpy is a may-store to P (P and Q may
110; alias).
111define void @test7_atomic(ptr align 4 %p, ptr align 4 %q, ptr noalias align 4 %r) {
112; CHECK-LABEL: @test7_atomic(
113; CHECK-NEXT:    call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 4 [[Q:%.*]], ptr align 4 [[R:%.*]], i64 900, i32 4)
114; CHECK-NEXT:    store atomic i32 30, ptr [[P:%.*]] unordered, align 4
115; CHECK-NEXT:    ret void
116;
117  store atomic i32 10, ptr %p unordered, align 4       ;; dead.
118  call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 4 %q, ptr align 4 %r, i64 900, i32 4)
119  store atomic i32 30, ptr %p unordered, align 4
120  ret void
121}
122
123; Do not delete stores that are only partially killed.
124define i32 @test8() {
125; CHECK-LABEL: @test8(
126; CHECK-NEXT:    [[V:%.*]] = alloca i32, align 4
127; CHECK-NEXT:    store i32 1234567, ptr [[V]], align 4
128; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[V]], align 4
129; CHECK-NEXT:    ret i32 [[X]]
130;
131  %V = alloca i32
132  store i32 1234567, ptr %V
133  store i8 0, ptr %V
134  %X = load i32, ptr %V
135  ret i32 %X
136
137}
138
139; Test for byval handling.
140%struct.x = type { i32, i32, i32, i32 }
141define void @test9(ptr byval(%struct.x)  %a) nounwind  {
142; CHECK-LABEL: @test9(
143; CHECK-NEXT:    ret void
144;
145  store i32 1, ptr %a, align 4
146  ret void
147}
148
149; Test for inalloca handling.
150define void @test9_2(ptr inalloca(%struct.x) %a) nounwind {
151; CHECK-LABEL: @test9_2(
152; CHECK-NEXT:    ret void
153;
154  store i32 1, ptr %a, align 4
155  ret void
156}
157
158; Test for preallocated handling.
159define void @test9_3(ptr preallocated(%struct.x)  %a) nounwind  {
160; CHECK-LABEL: @test9_3(
161; CHECK-NEXT:    ret void
162;
163  store i32 1, ptr %a, align 4
164  ret void
165}
166
167; va_arg has fuzzy dependence, the store shouldn't be zapped.
168define double @test10(ptr %X) {
169; CHECK-LABEL: @test10(
170; CHECK-NEXT:    [[X_ADDR:%.*]] = alloca ptr, align 8
171; CHECK-NEXT:    store ptr [[X:%.*]], ptr [[X_ADDR]], align 8
172; CHECK-NEXT:    [[TMP_0:%.*]] = va_arg ptr [[X_ADDR]], double
173; CHECK-NEXT:    ret double [[TMP_0]]
174;
175  %X_addr = alloca ptr
176  store ptr %X, ptr %X_addr
177  %tmp.0 = va_arg ptr %X_addr, double
178  ret double %tmp.0
179}
180
181; DSE should delete the dead trampoline.
182declare void @test11f()
183define void @test11() {
184; CHECK-LABEL: @test11(
185; CHECK-NEXT:    ret void
186;
187  %storage = alloca [10 x i8], align 16		; <ptr> [#uses=1]
188  %cast = getelementptr [10 x i8], ptr %storage, i32 0, i32 0		; <ptr> [#uses=1]
189  call void @llvm.init.trampoline( ptr %cast, ptr @test11f, ptr null )		; <ptr> [#uses=1]
190  ret void
191}
192
193; Specialized store intrinsics should be removed if dead.
194define void @test_matrix_store(i64 %stride) {
195; CHECK-LABEL: @test_matrix_store(
196; CHECK-NEXT:    ret void
197;
198  %a = alloca [6 x float]
199  call void @llvm.matrix.column.major.store(<6 x float> zeroinitializer, ptr %a, i64 %stride, i1 false, i32 3, i32 2)
200  ret void
201}
202
203; %P doesn't escape, the DEAD instructions should be removed.
204declare void @may_unwind()
205define ptr @test_malloc_no_escape_before_return() {
206; CHECK-LABEL: @test_malloc_no_escape_before_return(
207; CHECK-NEXT:    [[PTR:%.*]] = tail call ptr @malloc(i64 4)
208; CHECK-NEXT:    call void @may_unwind()
209; CHECK-NEXT:    store i32 0, ptr [[PTR]], align 4
210; CHECK-NEXT:    ret ptr [[PTR]]
211;
212  %ptr = tail call ptr @malloc(i64 4)
213  %DEAD = load i32, ptr %ptr
214  %DEAD2 = add i32 %DEAD, 1
215  store i32 %DEAD2, ptr %ptr
216  call void @may_unwind()
217  store i32 0, ptr %ptr
218  ret ptr %ptr
219}
220
221define ptr @test_custom_malloc_no_escape_before_return() {
222; CHECK-LABEL: @test_custom_malloc_no_escape_before_return(
223; CHECK-NEXT:    [[PTR:%.*]] = tail call ptr @custom_malloc(i32 4)
224; CHECK-NEXT:    call void @may_unwind()
225; CHECK-NEXT:    store i32 0, ptr [[PTR]], align 4
226; CHECK-NEXT:    ret ptr [[PTR]]
227;
228  %ptr = tail call ptr @custom_malloc(i32 4)
229  %DEAD = load i32, ptr %ptr
230  %DEAD2 = add i32 %DEAD, 1
231  store i32 %DEAD2, ptr %ptr
232  call void @may_unwind()
233  store i32 0, ptr %ptr
234  ret ptr %ptr
235}
236
237define ptr addrspace(1) @test13_addrspacecast() {
238; CHECK-LABEL: @test13_addrspacecast(
239; CHECK-NEXT:    [[P:%.*]] = tail call ptr @malloc(i64 4)
240; CHECK-NEXT:    [[P_AC:%.*]] = addrspacecast ptr [[P]] to ptr addrspace(1)
241; CHECK-NEXT:    call void @may_unwind()
242; CHECK-NEXT:    store i32 0, ptr addrspace(1) [[P_AC]], align 4
243; CHECK-NEXT:    ret ptr addrspace(1) [[P_AC]]
244;
245  %p = tail call ptr @malloc(i64 4)
246  %p.ac = addrspacecast ptr %p to ptr addrspace(1)
247  %DEAD = load i32, ptr addrspace(1) %p.ac
248  %DEAD2 = add i32 %DEAD, 1
249  store i32 %DEAD2, ptr addrspace(1) %p.ac
250  call void @may_unwind()
251  store i32 0, ptr addrspace(1) %p.ac
252  ret ptr addrspace(1) %p.ac
253}
254
255
256declare noalias ptr @malloc(i64) willreturn allockind("alloc,uninitialized")
257declare noalias ptr @custom_malloc(i32) willreturn
258declare noalias ptr @calloc(i64, i64) willreturn allockind("alloc,zeroed")
259
260define void @test14(ptr %Q) {
261; CHECK-LABEL: @test14(
262; CHECK-NEXT:    ret void
263;
264  %P = alloca i32
265  %DEAD = load i32, ptr %Q
266  store i32 %DEAD, ptr %P
267  ret void
268
269}
270
271; The store here is not dead because the byval call reads it.
272declare void @test19f(ptr byval({i32}) align 4 %P)
273
274define void @test19(ptr nocapture byval({i32}) align 4 %arg5) nounwind ssp {
275; CHECK-LABEL: @test19(
276; CHECK-NEXT:  bb:
277; CHECK-NEXT:    store i32 912, ptr [[ARG5:%.*]], align 4
278; CHECK-NEXT:    call void @test19f(ptr byval({ i32 }) align 4 [[ARG5]])
279; CHECK-NEXT:    ret void
280;
281bb:
282  store i32 912, ptr %arg5
283  call void @test19f(ptr byval({i32}) align 4 %arg5)
284  ret void
285
286}
287
288define void @malloc_no_escape() {
289; CHECK-LABEL: @malloc_no_escape(
290; CHECK-NEXT:    ret void
291;
292  %m = call ptr @malloc(i64 24)
293  store i8 0, ptr %m
294  ret void
295}
296
297define void @custom_malloc_no_escape() {
298; CHECK-LABEL: @custom_malloc_no_escape(
299; CHECK-NEXT:    [[M:%.*]] = call ptr @custom_malloc(i32 24)
300; CHECK-NEXT:    ret void
301;
302  %m = call ptr @custom_malloc(i32 24)
303  store i8 0, ptr %m
304  ret void
305}
306
307define void @test21() {
308; CHECK-LABEL: @test21(
309; CHECK-NEXT:    ret void
310;
311  %m = call ptr @calloc(i64 9, i64 7)
312  store i8 0, ptr %m
313  ret void
314}
315
316; Currently elimination of stores at the end of a function is limited to a
317; single underlying object, for compile-time. This case appears to not be
318; very important in practice.
319define void @test22(i1 %i, i32 %k, i32 %m) nounwind {
320; CHECK-LABEL: @test22(
321; CHECK-NEXT:    [[K_ADDR:%.*]] = alloca i32, align 4
322; CHECK-NEXT:    [[M_ADDR:%.*]] = alloca i32, align 4
323; CHECK-NEXT:    [[K_ADDR_M_ADDR:%.*]] = select i1 [[I:%.*]], ptr [[K_ADDR]], ptr [[M_ADDR]]
324; CHECK-NEXT:    store i32 0, ptr [[K_ADDR_M_ADDR]], align 4
325; CHECK-NEXT:    ret void
326;
327  %k.addr = alloca i32
328  %m.addr = alloca i32
329  %k.addr.m.addr = select i1 %i, ptr %k.addr, ptr %m.addr
330  store i32 0, ptr %k.addr.m.addr, align 4
331  ret void
332}
333
334; PR13547
335declare noalias ptr @strdup(ptr nocapture) nounwind
336define noalias ptr @test23() nounwind uwtable ssp {
337; CHECK-LABEL: @test23(
338; CHECK-NEXT:    [[X:%.*]] = alloca [2 x i8], align 1
339; CHECK-NEXT:    store i8 97, ptr [[X]], align 1
340; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1
341; CHECK-NEXT:    store i8 0, ptr [[ARRAYIDX1]], align 1
342; CHECK-NEXT:    [[CALL:%.*]] = call ptr @strdup(ptr [[X]]) #[[ATTR5:[0-9]+]]
343; CHECK-NEXT:    ret ptr [[CALL]]
344;
345  %x = alloca [2 x i8], align 1
346  store i8 97, ptr %x, align 1
347  %arrayidx1 = getelementptr inbounds [2 x i8], ptr %x, i64 0, i64 1
348  store i8 0, ptr %arrayidx1, align 1
349  %call = call ptr @strdup(ptr %x) nounwind
350  ret ptr %call
351}
352
353; Make sure same sized store to later element is deleted
354define void @test24(ptr %a, i32 %b, i32 %c) nounwind {
355; CHECK-LABEL: @test24(
356; CHECK-NEXT:    store i32 [[B:%.*]], ptr [[A:%.*]], align 4
357; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i64 0, i64 1
358; CHECK-NEXT:    store i32 [[C:%.*]], ptr [[TMP1]], align 4
359; CHECK-NEXT:    ret void
360;
361  store i32 0, ptr %a, align 4
362  %1 = getelementptr inbounds [2 x i32], ptr %a, i64 0, i64 1
363  store i32 0, ptr %1, align 4
364  store i32 %b, ptr %a, align 4
365  %2 = getelementptr inbounds [2 x i32], ptr %a, i64 0, i64 1
366  store i32 %c, ptr %2, align 4
367  ret void
368}
369
370; Check another case like PR13547 where strdup is not like malloc.
371define ptr @test25(ptr %p) nounwind {
372; CHECK-LABEL: @test25(
373; CHECK-NEXT:    [[P_4:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
374; CHECK-NEXT:    [[TMP:%.*]] = load i8, ptr [[P_4]], align 1
375; CHECK-NEXT:    store i8 0, ptr [[P_4]], align 1
376; CHECK-NEXT:    [[Q:%.*]] = call ptr @strdup(ptr [[P]]) #[[ATTR13:[0-9]+]]
377; CHECK-NEXT:    store i8 [[TMP]], ptr [[P_4]], align 1
378; CHECK-NEXT:    ret ptr [[Q]]
379;
380  %p.4 = getelementptr i8, ptr %p, i64 4
381  %tmp = load i8, ptr %p.4, align 1
382  store i8 0, ptr %p.4, align 1
383  %q = call ptr @strdup(ptr %p) nounwind optsize
384  store i8 %tmp, ptr %p.4, align 1
385  ret ptr %q
386}
387
388; Don't remove redundant store because of may-aliased store.
389define i32 @test28(i1 %c, ptr %p, ptr %p2, i32 %i) {
390; CHECK-LABEL: @test28(
391; CHECK-NEXT:  entry:
392; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
393; CHECK-NEXT:    store i32 [[I:%.*]], ptr [[P2:%.*]], align 4
394; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
395; CHECK:       bb1:
396; CHECK-NEXT:    br label [[BB3:%.*]]
397; CHECK:       bb2:
398; CHECK-NEXT:    br label [[BB3]]
399; CHECK:       bb3:
400; CHECK-NEXT:    store i32 [[V]], ptr [[P]], align 4
401; CHECK-NEXT:    ret i32 0
402;
403entry:
404  %v = load i32, ptr %p, align 4
405
406  ; Might overwrite value at %p
407  store i32 %i, ptr %p2, align 4
408  br i1 %c, label %bb1, label %bb2
409bb1:
410  br label %bb3
411bb2:
412  br label %bb3
413bb3:
414  store i32 %v, ptr %p, align 4
415  ret i32 0
416}
417
418; Don't remove redundant store because of may-aliased store.
419define i32 @test29(i1 %c, ptr %p, ptr %p2, i32 %i) {
420; CHECK-LABEL: @test29(
421; CHECK-NEXT:  entry:
422; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
423; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
424; CHECK:       bb1:
425; CHECK-NEXT:    br label [[BB3:%.*]]
426; CHECK:       bb2:
427; CHECK-NEXT:    store i32 [[I:%.*]], ptr [[P2:%.*]], align 4
428; CHECK-NEXT:    br label [[BB3]]
429; CHECK:       bb3:
430; CHECK-NEXT:    store i32 [[V]], ptr [[P]], align 4
431; CHECK-NEXT:    ret i32 0
432;
433entry:
434  %v = load i32, ptr %p, align 4
435  br i1 %c, label %bb1, label %bb2
436bb1:
437  br label %bb3
438bb2:
439  ; Might overwrite value at %p
440  store i32 %i, ptr %p2, align 4
441  br label %bb3
442bb3:
443  store i32 %v, ptr %p, align 4
444  ret i32 0
445}
446
447declare void @unknown_func()
448
449; Don't remove redundant store because of unknown call.
450define i32 @test30(i1 %c, ptr %p, i32 %i) {
451; CHECK-LABEL: @test30(
452; CHECK-NEXT:  entry:
453; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
454; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
455; CHECK:       bb1:
456; CHECK-NEXT:    br label [[BB3:%.*]]
457; CHECK:       bb2:
458; CHECK-NEXT:    call void @unknown_func()
459; CHECK-NEXT:    br label [[BB3]]
460; CHECK:       bb3:
461; CHECK-NEXT:    store i32 [[V]], ptr [[P]], align 4
462; CHECK-NEXT:    ret i32 0
463;
464entry:
465  %v = load i32, ptr %p, align 4
466  br i1 %c, label %bb1, label %bb2
467bb1:
468  br label %bb3
469bb2:
470  ; Might overwrite value at %p
471  call void @unknown_func()
472  br label %bb3
473bb3:
474  store i32 %v, ptr %p, align 4
475  ret i32 0
476}
477
478; Don't remove redundant store in a loop with a may-alias store.
479define i32 @test32(i1 %c, ptr %p, i32 %i, i1 %arg) {
480; CHECK-LABEL: @test32(
481; CHECK-NEXT:  entry:
482; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
483; CHECK-NEXT:    br label [[BB1:%.*]]
484; CHECK:       bb1:
485; CHECK-NEXT:    store i32 [[V]], ptr [[P]], align 4
486; CHECK-NEXT:    call void @unknown_func()
487; CHECK-NEXT:    br i1 %arg, label [[BB1]], label [[BB2:%.*]]
488; CHECK:       bb2:
489; CHECK-NEXT:    ret i32 0
490;
491entry:
492  %v = load i32, ptr %p, align 4
493  br label %bb1
494bb1:
495  store i32 %v, ptr %p, align 4
496  ; Might read and overwrite value at %p
497  call void @unknown_func()
498  br i1 %arg, label %bb1, label %bb2
499bb2:
500  ret i32 0
501}
502
503; We cannot remove any stores, because @unknown_func may unwind and the caller
504; may read %p while unwinding.
505define void @test34(ptr noalias %p) {
506; CHECK-LABEL: @test34(
507; CHECK-NEXT:    store i32 1, ptr [[P:%.*]], align 4
508; CHECK-NEXT:    call void @unknown_func()
509; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
510; CHECK-NEXT:    ret void
511;
512  store i32 1, ptr %p
513  call void @unknown_func()
514  store i32 0, ptr %p
515  ret void
516}
517
518; Same as previous case, but with a dead_on_unwind argument.
519define void @test34_dead_on_unwind(ptr noalias dead_on_unwind %p) {
520; CHECK-LABEL: @test34_dead_on_unwind(
521; CHECK-NEXT:    call void @unknown_func()
522; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
523; CHECK-NEXT:    ret void
524;
525  store i32 1, ptr %p
526  call void @unknown_func()
527  store i32 0, ptr %p
528  ret void
529}
530
531; Remove redundant store even with an unwinding function in the same block
532define void @test35(ptr noalias %p) {
533; CHECK-LABEL: @test35(
534; CHECK-NEXT:    call void @unknown_func()
535; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
536; CHECK-NEXT:    ret void
537;
538  call void @unknown_func()
539  store i32 1, ptr %p
540  store i32 0, ptr %p
541  ret void
542}
543
544; We cannot optimize away the first memmove since %P could overlap with %Q.
545define void @test36(ptr %P, ptr %Q) {
546; CHECK-LABEL: @test36(
547; CHECK-NEXT:    tail call void @llvm.memmove.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
548; CHECK-NEXT:    tail call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[Q]], i64 12, i1 false)
549; CHECK-NEXT:    ret void
550;
551
552  tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
553  tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
554  ret void
555}
556
557define void @test36_atomic(ptr %P, ptr %Q) {
558; CHECK-LABEL: @test36_atomic(
559; CHECK-NEXT:    tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
560; CHECK-NEXT:    tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[Q]], i64 12, i32 1)
561; CHECK-NEXT:    ret void
562;
563
564  tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
565  tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
566  ret void
567}
568
569define void @test37(ptr %P, ptr %Q, ptr %R) {
570; CHECK-LABEL: @test37(
571; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
572; CHECK-NEXT:    tail call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 12, i1 false)
573; CHECK-NEXT:    ret void
574;
575
576  tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
577  tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %R, i64 12, i1 false)
578  ret void
579}
580
581define void @test37_atomic(ptr %P, ptr %Q, ptr %R) {
582; CHECK-LABEL: @test37_atomic(
583; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
584; CHECK-NEXT:    tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 12, i32 1)
585; CHECK-NEXT:    ret void
586;
587
588  tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
589  tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 12, i32 1)
590  ret void
591}
592
593; See PR11763 - LLVM allows memcpy's source and destination to be equal (but not
594; inequal and overlapping).
595define void @test38(ptr %P, ptr %Q, ptr %R) {
596; CHECK-LABEL: @test38(
597; CHECK-NEXT:    tail call void @llvm.memmove.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
598; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 12, i1 false)
599; CHECK-NEXT:    ret void
600;
601
602  tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
603  tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %R, i64 12, i1 false)
604  ret void
605}
606
607; See PR11763 - LLVM allows memcpy's source and destination to be equal (but not
608; inequal and overlapping).
609define void @test38_atomic(ptr %P, ptr %Q, ptr %R) {
610; CHECK-LABEL: @test38_atomic(
611; CHECK-NEXT:    tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
612; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 12, i32 1)
613; CHECK-NEXT:    ret void
614;
615
616  tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
617  tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 12, i32 1)
618  ret void
619}
620
621define void @test39(ptr %P, ptr %Q, ptr %R) {
622; CHECK-LABEL: @test39(
623; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
624; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 8, i1 false)
625; CHECK-NEXT:    ret void
626;
627
628  tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
629  tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %R, i64 8, i1 false)
630  ret void
631}
632
633define void @test39_atomic(ptr %P, ptr %Q, ptr %R) {
634; CHECK-LABEL: @test39_atomic(
635; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
636; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 8, i32 1)
637; CHECK-NEXT:    ret void
638;
639
640  tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
641  tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 8, i32 1)
642  ret void
643}
644
645declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)
646declare void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i32)
647
648declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind
649declare void @llvm.lifetime.end.p0(i64, ptr nocapture) nounwind
650define void @test40(ptr noalias %Pp, ptr noalias %Q)  {
651; CHECK-LABEL: @test40(
652; CHECK-NEXT:  entry:
653; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
654; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[A]])
655; CHECK-NEXT:    [[PC:%.*]] = load ptr, ptr [[PP:%.*]], align 8
656; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 4 [[A]], ptr align 4 [[Q:%.*]], i64 4, i1 false)
657; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[PC]], ptr nonnull align 4 [[A]], i64 4, i1 true)
658; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[A]])
659; CHECK-NEXT:    ret void
660;
661entry:
662  %A = alloca i32, align 4
663  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %A)
664  %Pc = load ptr, ptr %Pp, align 8
665  call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 4 %A, ptr align 4 %Q, i64 4, i1 false)
666  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %Pc, ptr nonnull align 4 %A, i64 4, i1 true)
667  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %A)
668  ret void
669}
670
671declare void @free(ptr nocapture) allockind("free")
672
673; We cannot remove `store i32 1, ptr %p`, because @unknown_func may unwind
674; and the caller may read %p while unwinding.
675define void @test41(ptr noalias %P) {
676; CHECK-LABEL: @test41(
677; CHECK-NEXT:    store i32 1, ptr [[P:%.*]], align 4
678; CHECK-NEXT:    call void @unknown_func()
679; CHECK-NEXT:    call void @free(ptr [[P]])
680; CHECK-NEXT:    ret void
681;
682  store i32 1, ptr %P
683  call void @unknown_func()
684  store i32 2, ptr %P
685  call void @free(ptr %P)
686  ret void
687}
688
689define void @test42(ptr %P, ptr %Q) {
690; CHECK-LABEL: @test42(
691; CHECK-NEXT:    store i32 1, ptr [[P:%.*]], align 4
692; CHECK-NEXT:    store i32 2, ptr [[Q:%.*]], align 4
693; CHECK-NEXT:    store i8 3, ptr [[P]], align 1
694; CHECK-NEXT:    ret void
695;
696  store i32 1, ptr %P
697  store i32 2, ptr %Q
698  store i8 3, ptr %P
699  ret void
700}
701
702define void @test42a(ptr %P, ptr %Q) {
703; CHECK-LABEL: @test42a(
704; CHECK-NEXT:    store atomic i32 1, ptr [[P:%.*]] unordered, align 4
705; CHECK-NEXT:    store atomic i32 2, ptr [[Q:%.*]] unordered, align 4
706; CHECK-NEXT:    store atomic i8 3, ptr [[P]] unordered, align 4
707; CHECK-NEXT:    ret void
708;
709  store atomic i32 1, ptr %P unordered, align 4
710  store atomic i32 2, ptr %Q unordered, align 4
711  store atomic i8 3, ptr %P unordered, align 4
712  ret void
713}
714
715define void @test43a(ptr %P, ptr noalias %Q) {
716; CHECK-LABEL: @test43a(
717; CHECK-NEXT:  entry:
718; CHECK-NEXT:    store atomic i32 50331649, ptr [[P:%.*]] unordered, align 4
719; CHECK-NEXT:    store atomic i32 2, ptr [[Q:%.*]] unordered, align 4
720; CHECK-NEXT:    ret void
721;
722entry:
723  store atomic i32 1, ptr %P unordered, align 4
724  store atomic i32 2, ptr %Q unordered, align 4
725  store atomic i8 3, ptr %P unordered, align 4
726  ret void
727}
728
729; Some tests where volatile may block removing a store.
730
731; Here we can remove the first non-volatile store. We cannot remove the
732; volatile store.
733define void @test44_volatile(ptr %P) {
734; CHECK-LABEL: @test44_volatile(
735; CHECK-NEXT:    store volatile i32 2, ptr [[P:%.*]], align 4
736; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
737; CHECK-NEXT:    ret void
738;
739  store i32 1, ptr %P, align 4
740  store volatile i32 2, ptr %P, align 4
741  store i32 3, ptr %P, align 4
742  ret void
743}
744
745define void @test45_volatile(ptr %P) {
746; CHECK-LABEL: @test45_volatile(
747; CHECK-NEXT:    store volatile i32 2, ptr [[P:%.*]], align 4
748; CHECK-NEXT:    store volatile i32 3, ptr [[P]], align 4
749; CHECK-NEXT:    ret void
750;
751  store i32 1, ptr %P, align 4
752  store volatile i32 2, ptr %P, align 4
753  store volatile i32 3, ptr %P, align 4
754  ret void
755}
756
757define void @test46_volatile(ptr %P) {
758; CHECK-LABEL: @test46_volatile(
759; CHECK-NEXT:    store volatile i32 2, ptr [[P:%.*]], align 4
760; CHECK-NEXT:    store volatile i32 3, ptr [[P]], align 4
761; CHECK-NEXT:    ret void
762;
763  store volatile i32 2, ptr %P, align 4
764  store i32 1, ptr %P, align 4
765  store volatile i32 3, ptr %P, align 4
766  ret void
767}
768
769define void @test47_volatile(ptr %P) {
770; CHECK-LABEL: @test47_volatile(
771; CHECK-NEXT:    store volatile i32 2, ptr [[P:%.*]], align 4
772; CHECK-NEXT:    store volatile i32 3, ptr [[P]], align 4
773; CHECK-NEXT:    ret void
774;
775  store volatile i32 2, ptr %P, align 4
776  store volatile i32 3, ptr %P, align 4
777  ret void
778}
779
780define i32 @test48(ptr %P, ptr noalias %Q, ptr %R) {
781; CHECK-LABEL: @test48(
782; CHECK-NEXT:    store i32 2, ptr [[P:%.*]], align 4
783; CHECK-NEXT:    store i32 3, ptr [[Q:%.*]], align 4
784; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[R:%.*]], align 4
785; CHECK-NEXT:    ret i32 [[L]]
786;
787  store i32 1, ptr %Q
788  store i32 2, ptr %P
789  store i32 3, ptr %Q
790  %l = load i32, ptr %R
791  ret i32 %l
792}
793
794define void @test49() {
795; CHECK-LABEL: @test49(
796; CHECK-NEXT:  bb:
797; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr readonly null, i8 0, i64 0, i1 false)
798; CHECK-NEXT:    store ptr null, ptr null, align 8
799; CHECK-NEXT:    ret void
800;
801bb:
802  call void @llvm.memset.p0.i64(ptr readonly null, i8 0, i64 0, i1 false)
803  store ptr null, ptr null, align 8
804  ret void
805}
806