1 ; RUN: opt < %s -S -early-cse | FileCheck %s
3 ; CHECK-LABEL: @test12(
4 define i32 @test12(i1 %B, i32* %P1, i32* %P2) {
5 %load0 = load i32, i32* %P1
6 %1 = load atomic i32, i32* %P2 seq_cst, align 4
7 %load1 = load i32, i32* %P1
8 %sel = select i1 %B, i32 %load0, i32 %load1
10 ; CHECK: load i32, i32* %P1
11 ; CHECK: load i32, i32* %P1
14 ; CHECK-LABEL: @test13(
15 ; atomic to non-atomic forwarding is legal
16 define i32 @test13(i1 %B, i32* %P1) {
17 %a = load atomic i32, i32* %P1 seq_cst, align 4
18 %b = load i32, i32* %P1
21 ; CHECK: load atomic i32, i32* %P1
25 ; CHECK-LABEL: @test14(
26 ; atomic to unordered atomic forwarding is legal
27 define i32 @test14(i1 %B, i32* %P1) {
28 %a = load atomic i32, i32* %P1 seq_cst, align 4
29 %b = load atomic i32, i32* %P1 unordered, align 4
32 ; CHECK: load atomic i32, i32* %P1 seq_cst
33 ; CHECK-NEXT: ret i32 0
36 ; CHECK-LABEL: @test15(
37 ; implementation restriction: can't forward to stonger
39 define i32 @test15(i1 %B, i32* %P1, i32* %P2) {
40 %a = load atomic i32, i32* %P1 seq_cst, align 4
41 %b = load atomic i32, i32* %P1 seq_cst, align 4
44 ; CHECK: load atomic i32, i32* %P1
45 ; CHECK: load atomic i32, i32* %P1
48 ; CHECK-LABEL: @test16(
49 ; forwarding non-atomic to atomic is wrong! (However,
50 ; it would be legal to use the later value in place of the
51 ; former in this particular example. We just don't
53 define i32 @test16(i1 %B, i32* %P1, i32* %P2) {
54 %a = load i32, i32* %P1, align 4
55 %b = load atomic i32, i32* %P1 unordered, align 4
58 ; CHECK: load i32, i32* %P1
59 ; CHECK: load atomic i32, i32* %P1
62 ; Can't DSE across a full fence
63 define void @fence_seq_cst_store(i1 %B, i32* %P1, i32* %P2) {
64 ; CHECK-LABEL: @fence_seq_cst_store
68 store i32 0, i32* %P1, align 4
69 store atomic i32 0, i32* %P2 seq_cst, align 4
70 store i32 0, i32* %P1, align 4
74 ; Can't DSE across a full fence
75 define void @fence_seq_cst(i1 %B, i32* %P1, i32* %P2) {
76 ; CHECK-LABEL: @fence_seq_cst
78 ; CHECK: fence seq_cst
80 store i32 0, i32* %P1, align 4
82 store i32 0, i32* %P1, align 4
86 ; Can't DSE across a full fence
87 define void @fence_asm_sideeffect(i1 %B, i32* %P1, i32* %P2) {
88 ; CHECK-LABEL: @fence_asm_sideeffect
90 ; CHECK: call void asm sideeffect
92 store i32 0, i32* %P1, align 4
93 call void asm sideeffect "", ""()
94 store i32 0, i32* %P1, align 4
98 ; Can't DSE across a full fence
99 define void @fence_asm_memory(i1 %B, i32* %P1, i32* %P2) {
100 ; CHECK-LABEL: @fence_asm_memory
102 ; CHECK: call void asm
104 store i32 0, i32* %P1, align 4
105 call void asm "", "~{memory}"()
106 store i32 0, i32* %P1, align 4
110 ; Can't remove a volatile load
111 define i32 @volatile_load(i1 %B, i32* %P1, i32* %P2) {
112 %a = load i32, i32* %P1, align 4
113 %b = load volatile i32, i32* %P1, align 4
114 %res = sub i32 %a, %b
116 ; CHECK-LABEL: @volatile_load
117 ; CHECK: load i32, i32* %P1
118 ; CHECK: load volatile i32, i32* %P1
121 ; Can't remove redundant volatile loads
122 define i32 @redundant_volatile_load(i1 %B, i32* %P1, i32* %P2) {
123 %a = load volatile i32, i32* %P1, align 4
124 %b = load volatile i32, i32* %P1, align 4
125 %res = sub i32 %a, %b
127 ; CHECK-LABEL: @redundant_volatile_load
128 ; CHECK: load volatile i32, i32* %P1
129 ; CHECK: load volatile i32, i32* %P1
133 ; Can't DSE a volatile store
134 define void @volatile_store(i1 %B, i32* %P1, i32* %P2) {
135 ; CHECK-LABEL: @volatile_store
136 ; CHECK: store volatile
138 store volatile i32 0, i32* %P1, align 4
139 store i32 3, i32* %P1, align 4
143 ; Can't DSE a redundant volatile store
144 define void @redundant_volatile_store(i1 %B, i32* %P1, i32* %P2) {
145 ; CHECK-LABEL: @redundant_volatile_store
146 ; CHECK: store volatile
147 ; CHECK: store volatile
148 store volatile i32 0, i32* %P1, align 4
149 store volatile i32 0, i32* %P1, align 4
153 ; Can value forward from volatiles
154 define i32 @test20(i1 %B, i32* %P1, i32* %P2) {
155 %a = load volatile i32, i32* %P1, align 4
156 %b = load i32, i32* %P1, align 4
157 %res = sub i32 %a, %b
159 ; CHECK-LABEL: @test20
160 ; CHECK: load volatile i32, i32* %P1
164 ; Can DSE a non-volatile store in favor of a volatile one
165 ; currently a missed optimization
166 define void @test21(i1 %B, i32* %P1, i32* %P2) {
167 ; CHECK-LABEL: @test21
169 ; CHECK: store volatile
170 store i32 0, i32* %P1, align 4
171 store volatile i32 3, i32* %P1, align 4
175 ; Can DSE a normal store in favor of a unordered one
176 define void @test22(i1 %B, i32* %P1, i32* %P2) {
177 ; CHECK-LABEL: @test22
178 ; CHECK-NEXT: store atomic
179 store i32 0, i32* %P1, align 4
180 store atomic i32 3, i32* %P1 unordered, align 4
184 ; Can also DSE a unordered store in favor of a normal one
185 define void @test23(i1 %B, i32* %P1, i32* %P2) {
186 ; CHECK-LABEL: @test23
187 ; CHECK-NEXT: store i32 0
188 store atomic i32 3, i32* %P1 unordered, align 4
189 store i32 0, i32* %P1, align 4
193 ; As an implementation limitation, can't remove ordered stores
194 ; Note that we could remove the earlier store if we could
195 ; represent the required ordering.
196 define void @test24(i1 %B, i32* %P1, i32* %P2) {
197 ; CHECK-LABEL: @test24
198 ; CHECK-NEXT: store atomic
199 ; CHECK-NEXT: store i32 0
200 store atomic i32 3, i32* %P1 release, align 4
201 store i32 0, i32* %P1, align 4
205 ; Can't remove volatile stores - each is independently observable and
206 ; the count of such stores is an observable program side effect.
207 define void @test25(i1 %B, i32* %P1, i32* %P2) {
208 ; CHECK-LABEL: @test25
209 ; CHECK-NEXT: store volatile
210 ; CHECK-NEXT: store volatile
211 store volatile i32 3, i32* %P1, align 4
212 store volatile i32 0, i32* %P1, align 4
216 ; Can DSE a unordered store in favor of a unordered one
217 define void @test26(i1 %B, i32* %P1, i32* %P2) {
218 ; CHECK-LABEL: @test26
219 ; CHECK-NEXT: store atomic i32 3, i32* %P1 unordered, align 4
221 store atomic i32 0, i32* %P1 unordered, align 4
222 store atomic i32 3, i32* %P1 unordered, align 4
226 ; Can DSE a unordered store in favor of a ordered one,
227 ; but current don't due to implementation limits
228 define void @test27(i1 %B, i32* %P1, i32* %P2) {
229 ; CHECK-LABEL: @test27
230 ; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
231 ; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
233 store atomic i32 0, i32* %P1 unordered, align 4
234 store atomic i32 3, i32* %P1 release, align 4
238 ; Can DSE an unordered atomic store in favor of an
239 ; ordered one, but current don't due to implementation limits
240 define void @test28(i1 %B, i32* %P1, i32* %P2) {
241 ; CHECK-LABEL: @test28
242 ; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
243 ; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
245 store atomic i32 0, i32* %P1 unordered, align 4
246 store atomic i32 3, i32* %P1 release, align 4
250 ; As an implementation limitation, can't remove ordered stores
252 define void @test29(i1 %B, i32* %P1, i32* %P2) {
253 ; CHECK-LABEL: @test29
254 ; CHECK-NEXT: store atomic
255 ; CHECK-NEXT: store atomic
256 store atomic i32 3, i32* %P1 release, align 4
257 store atomic i32 0, i32* %P1 unordered, align 4