1; RUN: opt < %s -S -early-cse | FileCheck %s
2; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
3
4; CHECK-LABEL: @test12(
5define i32 @test12(i1 %B, i32* %P1, i32* %P2) {
6  %load0 = load i32, i32* %P1
7  %1 = load atomic i32, i32* %P2 seq_cst, align 4
8  %load1 = load i32, i32* %P1
9  %sel = select i1 %B, i32 %load0, i32 %load1
10  ret i32 %sel
11  ; CHECK: load i32, i32* %P1
12  ; CHECK: load i32, i32* %P1
13}
14
15; CHECK-LABEL: @test13(
16; atomic to non-atomic forwarding is legal
17define i32 @test13(i1 %B, i32* %P1) {
18  %a = load atomic i32, i32* %P1 seq_cst, align 4
19  %b = load i32, i32* %P1
20  %res = sub i32 %a, %b
21  ret i32 %res
22  ; CHECK: load atomic i32, i32* %P1
23  ; CHECK: ret i32 0
24}
25
26; CHECK-LABEL: @test14(
27; atomic to unordered atomic forwarding is legal
28define i32 @test14(i1 %B, i32* %P1) {
29  %a = load atomic i32, i32* %P1 seq_cst, align 4
30  %b = load atomic i32, i32* %P1 unordered, align 4
31  %res = sub i32 %a, %b
32  ret i32 %res
33  ; CHECK: load atomic i32, i32* %P1 seq_cst
34  ; CHECK-NEXT: ret i32 0
35}
36
37; CHECK-LABEL: @test15(
38; implementation restriction: can't forward to stonger
39; than unordered
40define i32 @test15(i1 %B, i32* %P1, i32* %P2) {
41  %a = load atomic i32, i32* %P1 seq_cst, align 4
42  %b = load atomic i32, i32* %P1 seq_cst, align 4
43  %res = sub i32 %a, %b
44  ret i32 %res
45  ; CHECK: load atomic i32, i32* %P1
46  ; CHECK: load atomic i32, i32* %P1
47}
48
49; CHECK-LABEL: @test16(
50; forwarding non-atomic to atomic is wrong! (However,
51; it would be legal to use the later value in place of the
52; former in this particular example.  We just don't
53; do that right now.)
54define i32 @test16(i1 %B, i32* %P1, i32* %P2) {
55  %a = load i32, i32* %P1, align 4
56  %b = load atomic i32, i32* %P1 unordered, align 4
57  %res = sub i32 %a, %b
58  ret i32 %res
59  ; CHECK: load i32, i32* %P1
60  ; CHECK: load atomic i32, i32* %P1
61}
62
63; Can't DSE across a full fence
64define void @fence_seq_cst_store(i1 %B, i32* %P1, i32* %P2) {
65; CHECK-LABEL: @fence_seq_cst_store
66; CHECK: store
67; CHECK: store atomic
68; CHECK: store
69  store i32 0, i32* %P1, align 4
70  store atomic i32 0, i32* %P2 seq_cst, align 4
71  store i32 0, i32* %P1, align 4
72  ret void
73}
74
75; Can't DSE across a full fence
76define void @fence_seq_cst(i1 %B, i32* %P1, i32* %P2) {
77; CHECK-LABEL: @fence_seq_cst
78; CHECK: store
79; CHECK: fence seq_cst
80; CHECK: store
81  store i32 0, i32* %P1, align 4
82  fence seq_cst
83  store i32 0, i32* %P1, align 4
84  ret void
85}
86
87; Can't DSE across a full fence
88define void @fence_asm_sideeffect(i1 %B, i32* %P1, i32* %P2) {
89; CHECK-LABEL: @fence_asm_sideeffect
90; CHECK: store
91; CHECK: call void asm sideeffect
92; CHECK: store
93  store i32 0, i32* %P1, align 4
94  call void asm sideeffect "", ""()
95  store i32 0, i32* %P1, align 4
96  ret void
97}
98
99; Can't DSE across a full fence
100define void @fence_asm_memory(i1 %B, i32* %P1, i32* %P2) {
101; CHECK-LABEL: @fence_asm_memory
102; CHECK: store
103; CHECK: call void asm
104; CHECK: store
105  store i32 0, i32* %P1, align 4
106  call void asm "", "~{memory}"()
107  store i32 0, i32* %P1, align 4
108  ret void
109}
110
111; Can't remove a volatile load
112define i32 @volatile_load(i1 %B, i32* %P1, i32* %P2) {
113  %a = load i32, i32* %P1, align 4
114  %b = load volatile i32, i32* %P1, align 4
115  %res = sub i32 %a, %b
116  ret i32 %res
117  ; CHECK-LABEL: @volatile_load
118  ; CHECK: load i32, i32* %P1
119  ; CHECK: load volatile i32, i32* %P1
120}
121
122; Can't remove redundant volatile loads
123define i32 @redundant_volatile_load(i1 %B, i32* %P1, i32* %P2) {
124  %a = load volatile i32, i32* %P1, align 4
125  %b = load volatile i32, i32* %P1, align 4
126  %res = sub i32 %a, %b
127  ret i32 %res
128  ; CHECK-LABEL: @redundant_volatile_load
129  ; CHECK: load volatile i32, i32* %P1
130  ; CHECK: load volatile i32, i32* %P1
131  ; CHECK: sub
132}
133
134; Can't DSE a volatile store
135define void @volatile_store(i1 %B, i32* %P1, i32* %P2) {
136; CHECK-LABEL: @volatile_store
137; CHECK: store volatile
138; CHECK: store
139  store volatile i32 0, i32* %P1, align 4
140  store i32 3, i32* %P1, align 4
141  ret void
142}
143
144; Can't DSE a redundant volatile store
145define void @redundant_volatile_store(i1 %B, i32* %P1, i32* %P2) {
146; CHECK-LABEL: @redundant_volatile_store
147; CHECK: store volatile
148; CHECK: store volatile
149  store volatile i32 0, i32* %P1, align 4
150  store volatile i32 0, i32* %P1, align 4
151  ret void
152}
153
154; Can value forward from volatiles
155define i32 @test20(i1 %B, i32* %P1, i32* %P2) {
156  %a = load volatile i32, i32* %P1, align 4
157  %b = load i32, i32* %P1, align 4
158  %res = sub i32 %a, %b
159  ret i32 %res
160  ; CHECK-LABEL: @test20
161  ; CHECK: load volatile i32, i32* %P1
162  ; CHECK: ret i32 0
163}
164
165; Can DSE a non-volatile store in favor of a volatile one
166; currently a missed optimization
167define void @test21(i1 %B, i32* %P1, i32* %P2) {
168; CHECK-LABEL: @test21
169; CHECK: store
170; CHECK: store volatile
171  store i32 0, i32* %P1, align 4
172  store volatile i32 3, i32* %P1, align 4
173  ret void
174}
175
176; Can DSE a normal store in favor of a unordered one
177define void @test22(i1 %B, i32* %P1, i32* %P2) {
178; CHECK-LABEL: @test22
179; CHECK-NEXT: store atomic
180  store i32 0, i32* %P1, align 4
181  store atomic i32 3, i32* %P1 unordered, align 4
182  ret void
183}
184
185; Can also DSE a unordered store in favor of a normal one
186define void @test23(i1 %B, i32* %P1, i32* %P2) {
187; CHECK-LABEL: @test23
188; CHECK-NEXT: store i32 0
189  store atomic i32 3, i32* %P1 unordered, align 4
190  store i32 0, i32* %P1, align 4
191  ret void
192}
193
194; As an implementation limitation, can't remove ordered stores
195; Note that we could remove the earlier store if we could
196; represent the required ordering.
197define void @test24(i1 %B, i32* %P1, i32* %P2) {
198; CHECK-LABEL: @test24
199; CHECK-NEXT: store atomic
200; CHECK-NEXT: store i32 0
201  store atomic i32 3, i32* %P1 release, align 4
202  store i32 0, i32* %P1, align 4
203  ret void
204}
205
206; Can't remove volatile stores - each is independently observable and
207; the count of such stores is an observable program side effect.
208define void @test25(i1 %B, i32* %P1, i32* %P2) {
209; CHECK-LABEL: @test25
210; CHECK-NEXT: store volatile
211; CHECK-NEXT: store volatile
212  store volatile i32 3, i32* %P1, align 4
213  store volatile i32 0, i32* %P1, align 4
214  ret void
215}
216
217; Can DSE a unordered store in favor of a unordered one
218define void @test26(i1 %B, i32* %P1, i32* %P2) {
219; CHECK-LABEL: @test26
220; CHECK-NEXT: store atomic i32 3, i32* %P1 unordered, align 4
221; CHECK-NEXT: ret
222  store atomic i32 0, i32* %P1 unordered, align 4
223  store atomic i32 3, i32* %P1 unordered, align 4
224  ret void
225}
226
227; Can DSE a unordered store in favor of a ordered one,
228; but current don't due to implementation limits
229define void @test27(i1 %B, i32* %P1, i32* %P2) {
230; CHECK-LABEL: @test27
231; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
232; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
233; CHECK-NEXT: ret
234  store atomic i32 0, i32* %P1 unordered, align 4
235  store atomic i32 3, i32* %P1 release, align 4
236  ret void
237}
238
239; Can DSE an unordered atomic store in favor of an
240; ordered one, but current don't due to implementation limits
241define void @test28(i1 %B, i32* %P1, i32* %P2) {
242; CHECK-LABEL: @test28
243; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
244; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
245; CHECK-NEXT: ret
246  store atomic i32 0, i32* %P1 unordered, align 4
247  store atomic i32 3, i32* %P1 release, align 4
248  ret void
249}
250
251; As an implementation limitation, can't remove ordered stores
252; see also: @test24
253define void @test29(i1 %B, i32* %P1, i32* %P2) {
254; CHECK-LABEL: @test29
255; CHECK-NEXT: store atomic
256; CHECK-NEXT: store atomic
257  store atomic i32 3, i32* %P1 release, align 4
258  store atomic i32 0, i32* %P1 unordered, align 4
259  ret void
260}
261