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