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