1 ; Verify that strict FP operations are not rescheduled
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
5 declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata)
6 declare float @llvm.sqrt.f32(float)
7 declare void @llvm.s390.sfpc(i32)
10 ; 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
15 ; We can move any FP operation across a (normal) store.
17 define void @f1(float %f1, float %f2, ptr %ptr1, ptr %ptr2) {
25 %sqrt1 = call float @llvm.sqrt.f32(float %f1)
26 %sqrt2 = call float @llvm.sqrt.f32(float %f2)
28 store float %sqrt1, ptr %ptr1
29 store float %sqrt2, ptr %ptr2
34 define void @f2(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
42 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
44 metadata !"round.dynamic",
45 metadata !"fpexcept.ignore") #0
46 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
48 metadata !"round.dynamic",
49 metadata !"fpexcept.ignore") #0
51 store float %sqrt1, ptr %ptr1
52 store float %sqrt2, ptr %ptr2
57 define void @f3(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
65 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
67 metadata !"round.dynamic",
68 metadata !"fpexcept.maytrap") #0
69 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
71 metadata !"round.dynamic",
72 metadata !"fpexcept.maytrap") #0
74 store float %sqrt1, ptr %ptr1
75 store float %sqrt2, ptr %ptr2
80 define void @f4(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
88 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
90 metadata !"round.dynamic",
91 metadata !"fpexcept.strict") #0
92 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
94 metadata !"round.dynamic",
95 metadata !"fpexcept.strict") #0
97 store float %sqrt1, ptr %ptr1
98 store float %sqrt2, ptr %ptr2
104 ; We can move a non-strict FP operation or a fpexcept.ignore
105 ; operation even across a volatile store, but not a fpexcept.maytrap
106 ; or fpexcept.strict operation.
108 define void @f5(float %f1, float %f2, ptr %ptr1, ptr %ptr2) {
116 %sqrt1 = call float @llvm.sqrt.f32(float %f1)
117 %sqrt2 = call float @llvm.sqrt.f32(float %f2)
119 store volatile float %sqrt1, ptr %ptr1
120 store volatile float %sqrt2, ptr %ptr2
125 define void @f6(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
133 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
135 metadata !"round.dynamic",
136 metadata !"fpexcept.ignore") #0
137 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
139 metadata !"round.dynamic",
140 metadata !"fpexcept.ignore") #0
142 store volatile float %sqrt1, ptr %ptr1
143 store volatile float %sqrt2, ptr %ptr2
148 define void @f7(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
156 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
158 metadata !"round.dynamic",
159 metadata !"fpexcept.maytrap") #0
160 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
162 metadata !"round.dynamic",
163 metadata !"fpexcept.maytrap") #0
165 store volatile float %sqrt1, ptr %ptr1
166 store volatile float %sqrt2, ptr %ptr2
171 define void @f8(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
179 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
181 metadata !"round.dynamic",
182 metadata !"fpexcept.strict") #0
183 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
185 metadata !"round.dynamic",
186 metadata !"fpexcept.strict") #0
188 store volatile float %sqrt1, ptr %ptr1
189 store volatile float %sqrt2, ptr %ptr2
195 ; No variant of FP operations can be scheduled across a SPFC.
197 define void @f9(float %f1, float %f2, ptr %ptr1, ptr %ptr2) {
205 %sqrt1 = call float @llvm.sqrt.f32(float %f1)
206 %sqrt2 = call float @llvm.sqrt.f32(float %f2)
208 call void @llvm.s390.sfpc(i32 0)
210 store float %sqrt1, ptr %ptr1
211 store float %sqrt2, ptr %ptr2
216 define void @f10(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
224 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
226 metadata !"round.dynamic",
227 metadata !"fpexcept.ignore") #0
228 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
230 metadata !"round.dynamic",
231 metadata !"fpexcept.ignore") #0
233 call void @llvm.s390.sfpc(i32 0) #0
235 store float %sqrt1, ptr %ptr1
236 store float %sqrt2, ptr %ptr2
241 define void @f11(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
249 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
251 metadata !"round.dynamic",
252 metadata !"fpexcept.maytrap") #0
253 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
255 metadata !"round.dynamic",
256 metadata !"fpexcept.maytrap") #0
258 call void @llvm.s390.sfpc(i32 0) #0
260 store float %sqrt1, ptr %ptr1
261 store float %sqrt2, ptr %ptr2
266 define void @f12(float %f1, float %f2, ptr %ptr1, ptr %ptr2) #0 {
274 %sqrt1 = call float @llvm.experimental.constrained.sqrt.f32(
276 metadata !"round.dynamic",
277 metadata !"fpexcept.strict") #0
278 %sqrt2 = call float @llvm.experimental.constrained.sqrt.f32(
280 metadata !"round.dynamic",
281 metadata !"fpexcept.strict") #0
283 call void @llvm.s390.sfpc(i32 0) #0
285 store float %sqrt1, ptr %ptr1
286 store float %sqrt2, ptr %ptr2
291 ; If the result of any FP operation is unused, it can be removed
292 ; -- except for fpexcept.strict operations.
294 define void @f13(float %f1) {
299 %sqrt = call float @llvm.sqrt.f32(float %f1)
304 define void @f14(float %f1) #0 {
309 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
311 metadata !"round.dynamic",
312 metadata !"fpexcept.ignore") #0
317 define void @f15(float %f1) #0 {
322 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
324 metadata !"round.dynamic",
325 metadata !"fpexcept.maytrap") #0
330 define void @f16(float %f1) #0 {
335 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
337 metadata !"round.dynamic",
338 metadata !"fpexcept.strict") #0
344 ; Verify that constrained intrinsics and memory operations get their
345 ; chains linked up properly.
347 define void @f17(float %in, ptr %out) #0 {
352 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
354 metadata !"round.dynamic",
355 metadata !"fpexcept.ignore") #0
356 store float %sqrt, ptr %out, align 4
357 tail call void @bar() #0
361 define void @f18(float %in, ptr %out) #0 {
366 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
368 metadata !"round.dynamic",
369 metadata !"fpexcept.ignore") #0
370 store float %sqrt, ptr %out, align 4
371 tail call void @bar() #0
375 define void @f19(float %in, ptr %out) #0 {
380 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
382 metadata !"round.dynamic",
383 metadata !"fpexcept.maytrap") #0
384 store float %sqrt, ptr %out, align 4
385 tail call void @bar() #0
389 define void @f20(float %in, ptr %out) #0 {
394 %sqrt = call float @llvm.experimental.constrained.sqrt.f32(
396 metadata !"round.dynamic",
397 metadata !"fpexcept.strict") #0
398 store float %sqrt, ptr %out, align 4
399 tail call void @bar() #0
403 attributes #0 = { strictfp }