1; RUN: opt < %s -S -basic-aa -licm -enable-mssa-loop-dependency=false -enable-new-pm=0 | FileCheck -check-prefixes=CHECK,AST %s
2; RUN: opt < %s -S -basic-aa -licm -enable-mssa-loop-dependency=true -enable-new-pm=0 | FileCheck -check-prefixes=CHECK,MSSA %s
3; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck -check-prefixes=CHECK,AST %s
4; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck -check-prefixes=CHECK,MSSA %s
5
6; Check that we can hoist unordered loads
7define i32 @test1(i32* nocapture %y) nounwind uwtable ssp {
8entry:
9  br label %loop
10
11loop:
12  %i = phi i32 [ %inc, %loop ], [ 0, %entry ]
13  %val = load atomic i32, i32* %y unordered, align 4
14  %inc = add nsw i32 %i, 1
15  %exitcond = icmp eq i32 %inc, %val
16  br i1 %exitcond, label %end, label %loop
17
18end:
19  ret i32 %val
20; CHECK-LABEL: define i32 @test1(
21; CHECK: load atomic
22; CHECK-NEXT: br label %loop
23}
24
25; Check that we don't sink/hoist monotonic loads
26; (Strictly speaking, it's not forbidden, but it's supposed to be possible to
27; use monotonic for spinlock-like constructs.)
28define i32 @test2(i32* nocapture %y) nounwind uwtable ssp {
29entry:
30  br label %loop
31
32loop:
33  %val = load atomic i32, i32* %y monotonic, align 4
34  %exitcond = icmp ne i32 %val, 0
35  br i1 %exitcond, label %end, label %loop
36
37end:
38  ret i32 %val
39; CHECK-LABEL: define i32 @test2(
40; CHECK: load atomic
41; CHECK-NEXT: %exitcond = icmp ne
42; CHECK-NEXT: br i1 %exitcond, label %end, label %loop
43}
44
45; Check that we hoist unordered around monotonic.
46; (The noalias shouldn't be necessary in theory, but LICM isn't quite that
47; smart yet.)
48define i32 @test3(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
49entry:
50  br label %loop
51
52loop:
53  %vala = load atomic i32, i32* %y monotonic, align 4
54  %valb = load atomic i32, i32* %x unordered, align 4
55  %exitcond = icmp ne i32 %vala, %valb
56  br i1 %exitcond, label %end, label %loop
57
58end:
59  ret i32 %vala
60; CHECK-LABEL: define i32 @test3(
61; CHECK: load atomic i32, i32* %x unordered
62; CHECK-NEXT: br label %loop
63}
64
65; We can sink an unordered store
66define i32 @test4(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
67entry:
68  br label %loop
69
70loop:
71  %vala = load atomic i32, i32* %y monotonic, align 4
72  store atomic i32 %vala, i32* %x unordered, align 4
73  %exitcond = icmp ne i32 %vala, 0
74  br i1 %exitcond, label %end, label %loop
75
76end:
77  ret i32 %vala
78; CHECK-LABEL: define i32 @test4(
79; CHECK-LABEL: loop:
80; CHECK: load atomic i32, i32* %y monotonic
81; CHECK-NOT: store
82; CHECK-LABEL: end:
83; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %vala
84; CHECK:   store atomic i32 %[[LCSSAPHI]], i32* %x unordered, align 4
85}
86
87; We currently don't handle ordered atomics.
88define i32 @test5(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
89entry:
90  br label %loop
91
92loop:
93  %vala = load atomic i32, i32* %y monotonic, align 4
94  store atomic i32 %vala, i32* %x release, align 4
95  %exitcond = icmp ne i32 %vala, 0
96  br i1 %exitcond, label %end, label %loop
97
98end:
99  ret i32 %vala
100; CHECK-LABEL: define i32 @test5(
101; CHECK: load atomic i32, i32* %y monotonic
102; CHECK-NEXT: store atomic
103}
104
105; We currently don't touch volatiles
106define i32 @test6(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
107entry:
108  br label %loop
109
110loop:
111  %vala = load atomic i32, i32* %y monotonic, align 4
112  store volatile i32 %vala, i32* %x, align 4
113  %exitcond = icmp ne i32 %vala, 0
114  br i1 %exitcond, label %end, label %loop
115
116end:
117  ret i32 %vala
118; CHECK-LABEL: define i32 @test6(
119; CHECK: load atomic i32, i32* %y monotonic
120; CHECK-NEXT: store volatile
121}
122
123; We currently don't touch volatiles
124define i32 @test6b(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
125entry:
126  br label %loop
127
128loop:
129  %vala = load atomic i32, i32* %y monotonic, align 4
130  store atomic volatile i32 %vala, i32* %x unordered, align 4
131  %exitcond = icmp ne i32 %vala, 0
132  br i1 %exitcond, label %end, label %loop
133
134end:
135  ret i32 %vala
136; CHECK-LABEL: define i32 @test6b(
137; CHECK: load atomic i32, i32* %y monotonic
138; CHECK-NEXT: store atomic volatile
139}
140
141; Mixing unorder atomics and normal loads/stores is
142; current unimplemented
143define i32 @test7(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
144entry:
145  br label %loop
146
147loop:
148  store i32 5, i32* %x
149  %vala = load atomic i32, i32* %y monotonic, align 4
150  store atomic i32 %vala, i32* %x unordered, align 4
151  %exitcond = icmp ne i32 %vala, 0
152  br i1 %exitcond, label %end, label %loop
153
154end:
155  ret i32 %vala
156; CHECK-LABEL: define i32 @test7(
157; CHECK: store i32 5, i32* %x
158; CHECK-NEXT: load atomic i32, i32* %y
159; CHECK-NEXT: store atomic i32
160}
161
162; Three provably noalias locations - we can sink normal and unordered, but
163;  not monotonic
164define i32 @test7b(i32* nocapture noalias %x, i32* nocapture %y, i32* noalias nocapture %z) nounwind uwtable ssp {
165entry:
166  br label %loop
167
168loop:
169  store i32 5, i32* %x
170  %vala = load atomic i32, i32* %y monotonic, align 4
171  store atomic i32 %vala, i32* %z unordered, align 4
172  %exitcond = icmp ne i32 %vala, 0
173  br i1 %exitcond, label %end, label %loop
174
175end:
176  ret i32 %vala
177; CHECK-LABEL: define i32 @test7b(
178; AST-LABEL: entry:
179; AST: store i32 5, i32* %x
180; CHECK-LABEL: loop:
181; CHECK: load atomic i32, i32* %y monotonic
182; CHECK-LABEL: end:
183; MSSA: store i32 5, i32* %x
184; CHECK: store atomic i32 %{{.+}}, i32* %z unordered, align 4
185}
186
187
188define i32 @test8(i32* nocapture noalias %x, i32* nocapture %y) {
189entry:
190  br label %loop
191
192loop:
193  %vala = load atomic i32, i32* %y monotonic, align 4
194  store atomic i32 %vala, i32* %x unordered, align 4
195  fence release
196  %exitcond = icmp ne i32 %vala, 0
197  br i1 %exitcond, label %end, label %loop
198
199end:
200  ret i32 %vala
201; CHECK-LABEL: define i32 @test8(
202; CHECK-LABEL: loop:
203; CHECK: load atomic i32, i32* %y monotonic
204; CHECK-NEXT: store atomic
205; CHECK-NEXT: fence
206}
207
208; Exact semantics of monotonic accesses are a bit vague in the C++ spec,
209; for the moment, be conservative and don't touch them.
210define i32 @test9(i32* nocapture noalias %x, i32* nocapture %y) {
211entry:
212  br label %loop
213
214loop:
215  %vala = load atomic i32, i32* %y monotonic, align 4
216  store atomic i32 %vala, i32* %x monotonic, align 4
217  %exitcond = icmp ne i32 %vala, 0
218  br i1 %exitcond, label %end, label %loop
219
220end:
221  ret i32 %vala
222; CHECK-LABEL: define i32 @test9(
223; CHECK-LABEL: loop:
224; CHECK: load atomic i32, i32* %y monotonic
225; CHECK-NEXT:   store atomic i32 %vala, i32* %x monotonic, align 4
226}
227