1; RUN: opt -basicaa -dse -S < %s | FileCheck %s
2
3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
4target triple = "x86_64-apple-macosx10.7.0"
5
6; Sanity tests for atomic stores.
7; Note that it turns out essentially every transformation DSE does is legal on
8; atomic ops, just some transformations are not allowed across release-acquire pairs.
9
10@x = common global i32 0, align 4
11@y = common global i32 0, align 4
12
13declare void @randomop(i32*)
14
15; DSE across unordered store (allowed)
16define void @test1() {
17; CHECK-LABEL: test1
18; CHECK-NOT: store i32 0
19; CHECK: store i32 1
20  store i32 0, i32* @x
21  store atomic i32 0, i32* @y unordered, align 4
22  store i32 1, i32* @x
23  ret void
24}
25
26; DSE across seq_cst load (allowed)
27define i32 @test2() {
28; CHECK-LABEL: test2
29; CHECK-NOT: store i32 0
30; CHECK: store i32 1
31  store i32 0, i32* @x
32  %x = load atomic i32* @y seq_cst, align 4
33  store i32 1, i32* @x
34  ret i32 %x
35}
36
37; DSE across seq_cst store (allowed)
38define void @test3() {
39; CHECK-LABEL: test3
40; CHECK-NOT: store i32 0
41; CHECK: store atomic i32 2
42  store i32 0, i32* @x
43  store atomic i32 2, i32* @y seq_cst, align 4
44  store i32 1, i32* @x
45  ret void
46}
47
48; DSE remove unordered store (allowed)
49define void @test4() {
50; CHECK-LABEL: test4
51; CHECK-NOT: store atomic
52; CHECK: store i32 1
53  store atomic i32 0, i32* @x unordered, align 4
54  store i32 1, i32* @x
55  ret void
56}
57
58; DSE unordered store overwriting non-atomic store (allowed)
59define void @test5() {
60; CHECK-LABEL: test5
61; CHECK: store atomic i32 1
62  store i32 0, i32* @x
63  store atomic i32 1, i32* @x unordered, align 4
64  ret void
65}
66
67; DSE no-op unordered atomic store (allowed)
68define void @test6() {
69; CHECK-LABEL: test6
70; CHECK-NOT: store
71; CHECK: ret void
72  %x = load atomic i32* @x unordered, align 4
73  store atomic i32 %x, i32* @x unordered, align 4
74  ret void
75}
76
77; DSE seq_cst store (be conservative; DSE doesn't have infrastructure
78; to reason about atomic operations).
79define void @test7() {
80; CHECK-LABEL: test7
81; CHECK: store atomic
82  %a = alloca i32
83  store atomic i32 0, i32* %a seq_cst, align 4
84  ret void
85}
86
87; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure
88; to reason about atomic operations).
89define i32 @test8() {
90; CHECK-LABEL: test8
91; CHECK: store
92; CHECK: load atomic
93  %a = alloca i32
94  call void @randomop(i32* %a)
95  store i32 0, i32* %a, align 4
96  %x = load atomic i32* @x seq_cst, align 4
97  ret i32 %x
98}
99
100; DSE across monotonic load (allowed as long as the eliminated store isUnordered)
101define i32 @test9() {
102; CHECK-LABEL: test9
103; CHECK-NOT: store i32 0
104; CHECK: store i32 1
105  store i32 0, i32* @x
106  %x = load atomic i32* @y monotonic, align 4
107  store i32 1, i32* @x
108  ret i32 %x
109}
110
111; DSE across monotonic store (allowed as long as the eliminated store isUnordered)
112define void @test10() {
113; CHECK-LABEL: test10
114; CHECK-NOT: store i32 0
115; CHECK: store i32 1
116  store i32 0, i32* @x
117  store atomic i32 42, i32* @y monotonic, align 4
118  store i32 1, i32* @x
119  ret void
120}
121
122; DSE across monotonic load (forbidden since the eliminated store is atomic)
123define i32 @test11() {
124; CHECK-LABEL: test11
125; CHECK: store atomic i32 0
126; CHECK: store atomic i32 1
127  store atomic i32 0, i32* @x monotonic, align 4
128  %x = load atomic i32* @y monotonic, align 4
129  store atomic i32 1, i32* @x monotonic, align 4
130  ret i32 %x
131}
132
133; DSE across monotonic store (forbidden since the eliminated store is atomic)
134define void @test12() {
135; CHECK-LABEL: test12
136; CHECK: store atomic i32 0
137; CHECK: store atomic i32 1
138  store atomic i32 0, i32* @x monotonic, align 4
139  store atomic i32 42, i32* @y monotonic, align 4
140  store atomic i32 1, i32* @x monotonic, align 4
141  ret void
142}
143
144; DSE is allowed across a pair of an atomic read and then write.
145define i32 @test13() {
146; CHECK-LABEL: test13
147; CHECK-NOT: store i32 0
148; CHECK: store i32 1
149  store i32 0, i32* @x
150  %x = load atomic i32* @y seq_cst, align 4
151  store atomic i32 %x, i32* @y seq_cst, align 4
152  store i32 1, i32* @x
153  ret i32 %x
154}
155
156; Same if it is acquire-release instead of seq_cst/seq_cst
157define i32 @test14() {
158; CHECK-LABEL: test14
159; CHECK-NOT: store i32 0
160; CHECK: store i32 1
161  store i32 0, i32* @x
162  %x = load atomic i32* @y acquire, align 4
163  store atomic i32 %x, i32* @y release, align 4
164  store i32 1, i32* @x
165  ret i32 %x
166}
167
168; But DSE is not allowed across a release-acquire pair.
169define i32 @test15() {
170; CHECK-LABEL: test15
171; CHECK: store i32 0
172; CHECK: store i32 1
173  store i32 0, i32* @x
174  store atomic i32 0, i32* @y release, align 4
175  %x = load atomic i32* @y acquire, align 4
176  store i32 1, i32* @x
177  ret i32 %x
178}
179