blob: 5091c3dc97badb93460b446fcd42a96979f6b473 [file] [log] [blame]
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +00001; Verify that strict FP operations are not rescheduled
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
4
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +00005declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata)
6declare float @llvm.sqrt.f32(float)
7declare void @llvm.s390.sfpc(i32)
Ulrich Weigand81ee4842020-01-14 14:04:53 +01008declare void @bar()
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +00009
Ulrich Weigand450c62e2019-07-16 15:55:45 +000010; The basic assumption of all following tests is that on z13, we never
11; want to see two square root instructions directly in a row, so the
12; post-RA scheduler will always schedule something else in between
13; whenever possible.
14
15; We can move any FP operation across a (normal) store.
16
17define void @f1(float %f1, float %f2, float *%ptr1, float *%ptr2) {
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000018; CHECK-LABEL: f1:
19; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +000020; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000021; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +000022; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000023; CHECK: br %r14
24
Ulrich Weigand450c62e2019-07-16 15:55:45 +000025 %sqrt1 = call float @llvm.sqrt.f32(float %f1)
26 %sqrt2 = call float @llvm.sqrt.f32(float %f2)
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000027
Ulrich Weigand450c62e2019-07-16 15:55:45 +000028 store float %sqrt1, float *%ptr1
29 store float %sqrt2, float *%ptr2
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000030
31 ret void
32}
33
Kevin P. Neal68b80522019-10-04 17:03:46 +000034define void @f2(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000035; CHECK-LABEL: f2:
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000036; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +000037; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000038; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +000039; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000040; CHECK: br %r14
41
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000042 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
Ulrich Weigand450c62e2019-07-16 15:55:45 +000043 float %f1,
44 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +000045 metadata !"fpexcept.ignore") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +000046 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000047 float %f2,
48 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +000049 metadata !"fpexcept.ignore") #0
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000050
Ulrich Weigand450c62e2019-07-16 15:55:45 +000051 store float %sqrt1, float *%ptr1
52 store float %sqrt2, float *%ptr2
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000053
54 ret void
55}
56
Kevin P. Neal68b80522019-10-04 17:03:46 +000057define void @f3(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000058; CHECK-LABEL: f3:
59; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +000060; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000061; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +000062; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000063; CHECK: br %r14
64
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000065 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
Ulrich Weigand450c62e2019-07-16 15:55:45 +000066 float %f1,
67 metadata !"round.dynamic",
Ulrich Weigand14cd4a52020-01-07 12:43:33 +010068 metadata !"fpexcept.maytrap") #0
69 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
70 float %f2,
71 metadata !"round.dynamic",
72 metadata !"fpexcept.maytrap") #0
73
74 store float %sqrt1, float *%ptr1
75 store float %sqrt2, float *%ptr2
76
77 ret void
78}
79
80define void @f4(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
81; CHECK-LABEL: f4:
82; CHECK: sqebr
83; CHECK: ste
84; CHECK: sqebr
85; CHECK: ste
86; CHECK: br %r14
87
88 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
89 float %f1,
90 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +000091 metadata !"fpexcept.strict") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +000092 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000093 float %f2,
94 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +000095 metadata !"fpexcept.strict") #0
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000096
Ulrich Weigand450c62e2019-07-16 15:55:45 +000097 store float %sqrt1, float *%ptr1
98 store float %sqrt2, float *%ptr2
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +000099
100 ret void
101}
102
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000103
104; We can move a non-strict FP operation or a fpexcept.ignore
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100105; operation even across a volatile store, but not a fpexcept.maytrap
106; or fpexcept.strict operation.
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000107
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100108define void @f5(float %f1, float %f2, float *%ptr1, float *%ptr2) {
109; CHECK-LABEL: f5:
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000110; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000111; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000112; CHECK: sqebr
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000113; CHECK: ste
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000114; CHECK: br %r14
115
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000116 %sqrt1 = call float @llvm.sqrt.f32(float %f1)
117 %sqrt2 = call float @llvm.sqrt.f32(float %f2)
118
119 store volatile float %sqrt1, float *%ptr1
120 store volatile float %sqrt2, float *%ptr2
121
122 ret void
123}
124
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100125define void @f6(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
126; CHECK-LABEL: f6:
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000127; CHECK: sqebr
128; CHECK: ste
129; CHECK: sqebr
130; CHECK: ste
131; CHECK: br %r14
132
133 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
134 float %f1,
135 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000136 metadata !"fpexcept.ignore") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000137 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
138 float %f2,
139 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000140 metadata !"fpexcept.ignore") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000141
142 store volatile float %sqrt1, float *%ptr1
143 store volatile float %sqrt2, float *%ptr2
144
145 ret void
146}
147
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100148define void @f7(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
149; CHECK-LABEL: f7:
150; CHECK: sqebr
151; CHECK: sqebr
152; CHECK: ste
153; CHECK: ste
154; CHECK: br %r14
155
156 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
157 float %f1,
158 metadata !"round.dynamic",
159 metadata !"fpexcept.maytrap") #0
160 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
161 float %f2,
162 metadata !"round.dynamic",
163 metadata !"fpexcept.maytrap") #0
164
165 store volatile float %sqrt1, float *%ptr1
166 store volatile float %sqrt2, float *%ptr2
167
168 ret void
169}
170
171define void @f8(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
172; CHECK-LABEL: f8:
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000173; CHECK: sqebr
174; CHECK: sqebr
175; CHECK: ste
176; CHECK: ste
177; CHECK: br %r14
178
179 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
180 float %f1,
181 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000182 metadata !"fpexcept.strict") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000183 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
184 float %f2,
185 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000186 metadata !"fpexcept.strict") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000187
188 store volatile float %sqrt1, float *%ptr1
189 store volatile float %sqrt2, float *%ptr2
190
191 ret void
192}
193
194
195; No variant of FP operations can be scheduled across a SPFC.
196
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100197define void @f9(float %f1, float %f2, float *%ptr1, float *%ptr2) {
198; CHECK-LABEL: f9:
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000199; CHECK: sqebr
200; CHECK: sqebr
201; CHECK: ste
202; CHECK: ste
203; CHECK: br %r14
204
205 %sqrt1 = call float @llvm.sqrt.f32(float %f1)
206 %sqrt2 = call float @llvm.sqrt.f32(float %f2)
207
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000208 call void @llvm.s390.sfpc(i32 0)
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000209
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000210 store float %sqrt1, float *%ptr1
211 store float %sqrt2, float *%ptr2
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000212
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000213 ret void
214}
215
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100216define void @f10(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
217; CHECK-LABEL: f10:
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000218; CHECK: sqebr
219; CHECK: sqebr
220; CHECK: ste
221; CHECK: ste
222; CHECK: br %r14
223
224 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
225 float %f1,
226 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000227 metadata !"fpexcept.ignore") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000228 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
229 float %f2,
230 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000231 metadata !"fpexcept.ignore") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000232
Kevin P. Neal68b80522019-10-04 17:03:46 +0000233 call void @llvm.s390.sfpc(i32 0) #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000234
235 store float %sqrt1, float *%ptr1
236 store float %sqrt2, float *%ptr2
237
238 ret void
239}
240
Ulrich Weigand14cd4a52020-01-07 12:43:33 +0100241define void @f11(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
242; CHECK-LABEL: f11:
243; CHECK: sqebr
244; CHECK: sqebr
245; CHECK: ste
246; CHECK: ste
247; CHECK: br %r14
248
249 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
250 float %f1,
251 metadata !"round.dynamic",
252 metadata !"fpexcept.maytrap") #0
253 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
254 float %f2,
255 metadata !"round.dynamic",
256 metadata !"fpexcept.maytrap") #0
257
258 call void @llvm.s390.sfpc(i32 0) #0
259
260 store float %sqrt1, float *%ptr1
261 store float %sqrt2, float *%ptr2
262
263 ret void
264}
265
266define void @f12(float %f1, float %f2, float *%ptr1, float *%ptr2) #0 {
267; CHECK-LABEL: f12:
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000268; CHECK: sqebr
269; CHECK: sqebr
270; CHECK: ste
271; CHECK: ste
272; CHECK: br %r14
273
274 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
275 float %f1,
276 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000277 metadata !"fpexcept.strict") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000278 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
279 float %f2,
280 metadata !"round.dynamic",
Kevin P. Neal68b80522019-10-04 17:03:46 +0000281 metadata !"fpexcept.strict") #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000282
Kevin P. Neal68b80522019-10-04 17:03:46 +0000283 call void @llvm.s390.sfpc(i32 0) #0
Ulrich Weigand450c62e2019-07-16 15:55:45 +0000284
285 store float %sqrt1, float *%ptr1
286 store float %sqrt2, float *%ptr2
Ulrich Weigand6c5d5ce2019-06-05 22:33:10 +0000287
288 ret void
289}
290
Ulrich Weigand04a86962020-01-13 14:37:07 +0100291; If the result of any FP operation is unused, it can be removed
292; -- except for fpexcept.strict operations.
293
294define void @f13(float %f1) {
295; CHECK-LABEL: f13:
296; CHECK-NOT: sqeb
297; CHECK: br %r14
298
299 %sqrt = call float @llvm.sqrt.f32(float %f1)
300
301 ret void
302}
303
Ulrich Weigand81ee4842020-01-14 14:04:53 +0100304define void @f14(float %f1) #0 {
Ulrich Weigand04a86962020-01-13 14:37:07 +0100305; CHECK-LABEL: f14:
306; CHECK-NOT: sqeb
307; CHECK: br %r14
308
309 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
310 float %f1,
311 metadata !"round.dynamic",
312 metadata !"fpexcept.ignore") #0
313
314 ret void
315}
316
Ulrich Weigand81ee4842020-01-14 14:04:53 +0100317define void @f15(float %f1) #0 {
Ulrich Weigand04a86962020-01-13 14:37:07 +0100318; CHECK-LABEL: f15:
319; CHECK-NOT: sqeb
320; CHECK: br %r14
321
322 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
323 float %f1,
324 metadata !"round.dynamic",
325 metadata !"fpexcept.maytrap") #0
326
327 ret void
328}
329
Ulrich Weigand81ee4842020-01-14 14:04:53 +0100330define void @f16(float %f1) #0 {
Ulrich Weigand04a86962020-01-13 14:37:07 +0100331; CHECK-LABEL: f16:
332; CHECK: sqebr
333; CHECK: br %r14
334
335 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
336 float %f1,
337 metadata !"round.dynamic",
338 metadata !"fpexcept.strict") #0
339
340 ret void
341}
342
Ulrich Weigand81ee4842020-01-14 14:04:53 +0100343
344; Verify that constrained intrinsics and memory operations get their
345; chains linked up properly.
346
347define void @f17(float %in, float* %out) #0 {
348; CHECK-LABEL: f17:
349; CHECK: sqebr
350; CHECK: ste
351; CHECK: jg bar
352 %sqrt = call float @llvm.sqrt.f32(float %in)
353 store float %sqrt, float* %out, align 4
354 tail call void @bar() #0
355 ret void
356}
357
358define void @f18(float %in, float* %out) #0 {
359; CHECK-LABEL: f18:
360; CHECK: sqebr
361; CHECK: ste
362; CHECK: jg bar
363 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
364 float %in,
365 metadata !"round.dynamic",
366 metadata !"fpexcept.ignore") #0
367 store float %sqrt, float* %out, align 4
368 tail call void @bar() #0
369 ret void
370}
371
372define void @f19(float %in, float* %out) #0 {
373; CHECK-LABEL: f19:
374; CHECK: sqebr
375; CHECK: ste
376; CHECK: jg bar
377 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
378 float %in,
379 metadata !"round.dynamic",
380 metadata !"fpexcept.maytrap") #0
381 store float %sqrt, float* %out, align 4
382 tail call void @bar() #0
383 ret void
384}
385
386define void @f20(float %in, float* %out) #0 {
387; CHECK-LABEL: f20:
388; CHECK: sqebr
389; CHECK: ste
390; CHECK: jg bar
391 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
392 float %in,
393 metadata !"round.dynamic",
394 metadata !"fpexcept.strict") #0
395 store float %sqrt, float* %out, align 4
396 tail call void @bar() #0
397 ret void
398}
399
Kevin P. Neal68b80522019-10-04 17:03:46 +0000400attributes #0 = { strictfp }