1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -dse -S | FileCheck %s
3; RUN: opt < %s -basic-aa -dse -enable-dse-memoryssa=false -S | FileCheck %s
4; RUN: opt < %s -aa-pipeline=basic-aa -passes=dse -S | FileCheck %s
5target 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"
6
7declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
8declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture, i8, i64, i32) nounwind
9declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
10declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind
11declare void @llvm.init.trampoline(i8*, i8*, i8*)
12
13
14;; Overwrite of memset by memcpy.
15define void @test17(i8* %P, i8* noalias %Q) nounwind ssp {
16; CHECK-LABEL: @test17(
17; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false)
18; CHECK-NEXT:    ret void
19;
20  tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false)
21  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
22  ret void
23}
24
25;; Overwrite of memset by memcpy.
26define void @test17_atomic(i8* %P, i8* noalias %Q) nounwind ssp {
27; CHECK-LABEL: @test17_atomic(
28; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1)
29; CHECK-NEXT:    ret void
30;
31  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %P, i8 42, i64 8, i32 1)
32  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
33  ret void
34}
35
36;; Overwrite of memset by memcpy. Overwrite is stronger atomicity. We can
37;; remove the memset.
38define void @test17_atomic_weaker(i8* %P, i8* noalias %Q) nounwind ssp {
39; CHECK-LABEL: @test17_atomic_weaker(
40; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1)
41; CHECK-NEXT:    ret void
42;
43  tail call void @llvm.memset.p0i8.i64(i8* align 1 %P, i8 42, i64 8, i1 false)
44  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
45  ret void
46}
47
48;; Overwrite of memset by memcpy. Overwrite is weaker atomicity. We can remove
49;; the memset.
50define void @test17_atomic_weaker_2(i8* %P, i8* noalias %Q) nounwind ssp {
51; CHECK-LABEL: @test17_atomic_weaker_2(
52; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i1 false)
53; CHECK-NEXT:    ret void
54;
55  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %P, i8 42, i64 8, i32 1)
56  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false)
57  ret void
58}
59
60; Should not delete the volatile memset.
61define void @test17v(i8* %P, i8* %Q) nounwind ssp {
62; CHECK-LABEL: @test17v(
63; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* [[P:%.*]], i8 42, i64 8, i1 true)
64; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P]], i8* [[Q:%.*]], i64 12, i1 false)
65; CHECK-NEXT:    ret void
66;
67  tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 true)
68  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
69  ret void
70}
71
72; See PR11763 - LLVM allows memcpy's source and destination to be equal (but not
73; inequal and overlapping).
74define void @test18(i8* %P, i8* %Q, i8* %R) nounwind ssp {
75; CHECK-LABEL: @test18(
76; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false)
77; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P]], i8* [[R:%.*]], i64 12, i1 false)
78; CHECK-NEXT:    ret void
79;
80  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
81  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false)
82  ret void
83}
84
85define void @test18_atomic(i8* %P, i8* %Q, i8* %R) nounwind ssp {
86; CHECK-LABEL: @test18_atomic(
87; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1)
88; CHECK-NEXT:    tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[R:%.*]], i64 12, i32 1)
89; CHECK-NEXT:    ret void
90;
91  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1)
92  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %R, i64 12, i32 1)
93  ret void
94}
95
96define void @test_memset_memcpy_inline(i8* noalias %P, i8* noalias %Q) {
97; CHECK-LABEL: @test_memset_memcpy_inline(
98; CHECK-NEXT:    tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i1 false)
99; CHECK-NEXT:    ret void
100;
101  tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false)
102  tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false)
103  ret void
104}
105
106define void @test_store_memcpy_inline(i8* noalias %P, i8* noalias %Q) {
107; CHECK-LABEL: @test_store_memcpy_inline(
108; CHECK-NEXT:    [[P_4:%.*]] = getelementptr i8, i8* [[P:%.*]], i64 4
109; CHECK-NEXT:    store i8 4, i8* [[P_4]], align 1
110; CHECK-NEXT:    tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[Q:%.*]], i64 4, i1 false)
111; CHECK-NEXT:    ret void
112;
113  store i8 0, i8* %P
114  %P.1 = getelementptr i8, i8* %P, i64 1
115  store i8 1, i8* %P.1
116  %P.4 = getelementptr i8, i8* %P, i64 4
117  store i8 4, i8* %P.4
118  tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 4, i1 false)
119  ret void
120}
121
122declare void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64 immarg, i1 immarg)
123