Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / InstSimplify / strictfp-fsub.ll
blobb55519e8374b60447906cf8927f10591408c05e7
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
5 ; constrained fsub
9 ; fsub X, +0 ==> X
12 define float @fsub_x_p0_defaultenv(float %a) #0 {
13 ; CHECK-LABEL: @fsub_x_p0_defaultenv(
14 ; CHECK-NEXT:    ret float [[A:%.*]]
16   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore")
17   ret float %ret
20 ; Missing nnan: must not fire.
21 define float @fsub_x_p0_ebmaytrap(float %a) #0 {
22 ; CHECK-LABEL: @fsub_x_p0_ebmaytrap(
23 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
24 ; CHECK-NEXT:    ret float [[RET]]
26   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
27   ret float %ret
30 define float @fsub_nnan_x_p0_ebmaytrap(float %a) #0 {
31 ; CHECK-LABEL: @fsub_nnan_x_p0_ebmaytrap(
32 ; CHECK-NEXT:    ret float [[A:%.*]]
34   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
35   ret float %ret
38 ; Missing nnan: must not fire.
39 define float @fsub_x_p0_ebstrict(float %a) #0 {
40 ; CHECK-LABEL: @fsub_x_p0_ebstrict(
41 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
42 ; CHECK-NEXT:    ret float [[RET]]
44   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
45   ret float %ret
48 ; The instruction is expected to remain, but the result isn't used.
49 define float @fsub_nnan_x_p0_ebstrict(float %a) #0 {
50 ; CHECK-LABEL: @fsub_nnan_x_p0_ebstrict(
51 ; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
52 ; CHECK-NEXT:    ret float [[A]]
54   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
55   ret float %ret
58 ; Test with a fast math flag set but that flag is not "nnan".
59 define float @fsub_ninf_x_p0_ebstrict(float %a) #0 {
60 ; CHECK-LABEL: @fsub_ninf_x_p0_ebstrict(
61 ; CHECK-NEXT:    [[RET:%.*]] = call ninf float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
62 ; CHECK-NEXT:    ret float [[RET]]
64   %ret = call ninf float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
65   ret float %ret
68 ; Round to -inf and if x is zero then the result is -0.0: must not fire
69 define float @fsub_x_p0_neginf(float %a) #0 {
70 ; CHECK-LABEL: @fsub_x_p0_neginf(
71 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.downward", metadata !"fpexcept.ignore")
72 ; CHECK-NEXT:    ret float [[RET]]
74   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.ignore")
75   ret float %ret
78 ; Dynamic rounding means the rounding mode might be to -inf:
79 ; Round to -inf and if x is zero then the result is -0.0: must not fire
80 define float @fsub_x_p0_dynamic(float %a) #0 {
81 ; CHECK-LABEL: @fsub_x_p0_dynamic(
82 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.ignore")
83 ; CHECK-NEXT:    ret float [[RET]]
85   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.dynamic", metadata !"fpexcept.ignore")
86   ret float %ret
89 ; With nsz we don't have to worry about -0.0 so the transform is valid.
90 define float @fsub_nsz_x_p0_neginf(float %a) #0 {
91 ; CHECK-LABEL: @fsub_nsz_x_p0_neginf(
92 ; CHECK-NEXT:    ret float [[A:%.*]]
94   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.ignore")
95   ret float %ret
98 ; With nsz we don't have to worry about -0.0 so the transform is valid.
99 define float @fsub_nsz_x_p0_dynamic(float %a) #0 {
100 ; CHECK-LABEL: @fsub_nsz_x_p0_dynamic(
101 ; CHECK-NEXT:    ret float [[A:%.*]]
103   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.dynamic", metadata !"fpexcept.ignore")
104   ret float %ret
108 ; fsub X, -0 ==> X, when we know X is not -0
109 ; (fast math flag: nsz)
112 define float @fold_fsub_nsz_x_n0_defaultenv(float %a) #0 {
113 ; CHECK-LABEL: @fold_fsub_nsz_x_n0_defaultenv(
114 ; CHECK-NEXT:    ret float [[A:%.*]]
116   %sub = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore")
117   ret float %sub
120 ; Missing nnan: must not fire.
121 define float @fold_fsub_nsz_x_n0_ebmaytrap(float %a) #0 {
122 ; CHECK-LABEL: @fold_fsub_nsz_x_n0_ebmaytrap(
123 ; CHECK-NEXT:    [[SUB:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
124 ; CHECK-NEXT:    ret float [[SUB]]
126   %sub = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
127   ret float %sub
130 define float @fold_fsub_nnan_nsz_x_n0_ebmaytrap(float %a) #0 {
131 ; CHECK-LABEL: @fold_fsub_nnan_nsz_x_n0_ebmaytrap(
132 ; CHECK-NEXT:    ret float [[A:%.*]]
134   %sub = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
135   ret float %sub
138 ; Missing nnan: must not fire.
139 define float @fold_fsub_nsz_x_n0_ebstrict(float %a) #0 {
140 ; CHECK-LABEL: @fold_fsub_nsz_x_n0_ebstrict(
141 ; CHECK-NEXT:    [[SUB:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
142 ; CHECK-NEXT:    ret float [[SUB]]
144   %sub = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
145   ret float %sub
148 ; The instruction is expected to remain, but the result isn't used.
149 define float @fold_fsub_nsz_nnan_x_n0_ebstrict(float %a) #0 {
150 ; CHECK-LABEL: @fold_fsub_nsz_nnan_x_n0_ebstrict(
151 ; CHECK-NEXT:    [[SUB:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
152 ; CHECK-NEXT:    ret float [[A]]
154   %sub = call nsz nnan float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
155   ret float %sub
159 ; fsub X, -0 ==> X, when we know X is not -0
160 ; (No "nsz" flags)
163 define float @fold_fsub_fabs_x_n0_defaultenv(float %a) #0 {
164 ; CHECK-LABEL: @fold_fsub_fabs_x_n0_defaultenv(
165 ; CHECK-NEXT:    [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0:[0-9]+]]
166 ; CHECK-NEXT:    ret float [[ABSA]]
168   %absa = call float @llvm.fabs.f32(float %a) #0
169   %sub = call float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore")
170   ret float %sub
173 ; Missing nnan: must not fire.
174 define float @fold_fsub_fabs_x_n0_ebmaytrap(float %a) #0 {
175 ; CHECK-LABEL: @fold_fsub_fabs_x_n0_ebmaytrap(
176 ; CHECK-NEXT:    [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]]
177 ; CHECK-NEXT:    [[SUB:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
178 ; CHECK-NEXT:    ret float [[SUB]]
180   %absa = call float @llvm.fabs.f32(float %a) #0
181   %sub = call float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
182   ret float %sub
185 define float @fold_fsub_fabs_nnan_x_n0_ebmaytrap(float %a) #0 {
186 ; CHECK-LABEL: @fold_fsub_fabs_nnan_x_n0_ebmaytrap(
187 ; CHECK-NEXT:    [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]]
188 ; CHECK-NEXT:    ret float [[ABSA]]
190   %absa = call float @llvm.fabs.f32(float %a) #0
191   %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
192   ret float %sub
195 ; Missing nnan: must not fire.
196 define float @fold_fsub_fabs_x_n0_ebstrict(float %a) #0 {
197 ; CHECK-LABEL: @fold_fsub_fabs_x_n0_ebstrict(
198 ; CHECK-NEXT:    [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]]
199 ; CHECK-NEXT:    [[SUB:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
200 ; CHECK-NEXT:    ret float [[SUB]]
202   %absa = call float @llvm.fabs.f32(float %a) #0
203   %sub = call float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
204   ret float %sub
207 ; The instruction is expected to remain, but the result isn't used.
208 define float @fold_fsub_fabs_nnan_x_n0_ebstrict(float %a) #0 {
209 ; CHECK-LABEL: @fold_fsub_fabs_nnan_x_n0_ebstrict(
210 ; CHECK-NEXT:    [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]]
211 ; CHECK-NEXT:    [[SUB:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict")
212 ; CHECK-NEXT:    ret float [[ABSA]]
214   %absa = call float @llvm.fabs.f32(float %a) #0
215   %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict")
216   ret float %sub
219 define float @fold_fsub_sitofp_x_n0_defaultenv(i32 %a) #0 {
220 ; CHECK-LABEL: @fold_fsub_sitofp_x_n0_defaultenv(
221 ; CHECK-NEXT:    [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
222 ; CHECK-NEXT:    ret float [[FPA]]
224   %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.ignore")
225   %sub = call float @llvm.experimental.constrained.fsub.f32(float %fpa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore")
226   ret float %sub
230 ; fsub -0.0, (fneg X) ==> X
233 define float @fsub_fneg_n0_fnX_defaultenv(float %a) #0 {
234 ; CHECK-LABEL: @fsub_fneg_n0_fnX_defaultenv(
235 ; CHECK-NEXT:    ret float [[A:%.*]]
237   %nega = fneg float %a
238   %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore")
239   ret float %ret
242 ; Missing nnan: must not fire.
243 define float @fsub_fneg_n0_fnX_ebmaytrap(float %a) #0 {
244 ; CHECK-LABEL: @fsub_fneg_n0_fnX_ebmaytrap(
245 ; CHECK-NEXT:    [[NEGA:%.*]] = fneg float [[A:%.*]]
246 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
247 ; CHECK-NEXT:    ret float [[RET]]
249   %nega = fneg float %a
250   %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
251   ret float %ret
254 define float @fsub_fneg_nnan_n0_fnX_ebmaytrap(float %a) #0 {
255 ; CHECK-LABEL: @fsub_fneg_nnan_n0_fnX_ebmaytrap(
256 ; CHECK-NEXT:    ret float [[A:%.*]]
258   %nega = fneg float %a
259   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
260   ret float %ret
263 ; Missing nnan: must not fire.
264 define float @fsub_fneg_n0_fnX_ebstrict(float %a) #0 {
265 ; CHECK-LABEL: @fsub_fneg_n0_fnX_ebstrict(
266 ; CHECK-NEXT:    [[NEGA:%.*]] = fneg float [[A:%.*]]
267 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
268 ; CHECK-NEXT:    ret float [[RET]]
270   %nega = fneg float %a
271   %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
272   ret float %ret
275 ; The instruction is expected to remain, but the result isn't used.
276 define float @fsub_fneg_nnan_n0_fnX_ebstrict(float %a) #0 {
277 ; CHECK-LABEL: @fsub_fneg_nnan_n0_fnX_ebstrict(
278 ; CHECK-NEXT:    [[NEGA:%.*]] = fneg float [[A:%.*]]
279 ; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
280 ; CHECK-NEXT:    ret float [[A]]
282   %nega = fneg float %a
283   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
284   ret float %ret
288 ; fsub -0.0, (fsub -0.0, X) ==> X
291 ; TODO: This won't fire without m_FNeg() knowing the constrained intrinsics.
292 define float @fsub_fsub_n0_fnX_defaultenv(float %a) #0 {
293 ; CHECK-LABEL: @fsub_fsub_n0_fnX_defaultenv(
294 ; CHECK-NEXT:    [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
295 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
296 ; CHECK-NEXT:    ret float [[RET]]
298   %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore")
299   %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore")
300   ret float %ret
303 ; Missing nnan: must not fire.
304 define float @fsub_fsub_n0_fnX_ebmaytrap(float %a) #0 {
305 ; CHECK-LABEL: @fsub_fsub_n0_fnX_ebmaytrap(
306 ; CHECK-NEXT:    [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
307 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
308 ; CHECK-NEXT:    ret float [[RET]]
310   %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
311   %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
312   ret float %ret
315 ; TODO: This won't fire without m_FNeg() knowing the constrained intrinsics.
316 define float @fsub_fsub_nnan_n0_fnX_ebmaytrap(float %a) #0 {
317 ; CHECK-LABEL: @fsub_fsub_nnan_n0_fnX_ebmaytrap(
318 ; CHECK-NEXT:    [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
319 ; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
320 ; CHECK-NEXT:    ret float [[RET]]
322   %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
323   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
324   ret float %ret
327 ; Missing nnan: must not fire.
328 define float @fsub_fsub_n0_fnX_ebstrict(float %a) #0 {
329 ; CHECK-LABEL: @fsub_fsub_n0_fnX_ebstrict(
330 ; CHECK-NEXT:    [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
331 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
332 ; CHECK-NEXT:    ret float [[RET]]
334   %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
335   %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
336   ret float %ret
339 ; TODO: This won't fire without m_FNeg() knowing the constrained intrinsics.
340 define float @fsub_fsub_nnan_n0_fnX_ebstrict(float %a) #0 {
341 ; CHECK-LABEL: @fsub_fsub_nnan_n0_fnX_ebstrict(
342 ; CHECK-NEXT:    [[NEGA:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
343 ; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
344 ; CHECK-NEXT:    ret float [[RET]]
346   %nega = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
347   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
348   ret float %ret
352 ; fsub 0.0, (fneg X) ==> X if signed zeros are ignored.
355 define float @fsub_fneg_nsz_p0_fnX_defaultenv(float %a) #0 {
356 ; CHECK-LABEL: @fsub_fneg_nsz_p0_fnX_defaultenv(
357 ; CHECK-NEXT:    ret float [[A:%.*]]
359   %nega = fneg float %a
360   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore")
361   ret float %ret
364 ; Missing nnan: must not fire.
365 define float @fsub_fneg_nsz_p0_fnX_ebmaytrap(float %a) #0 {
366 ; CHECK-LABEL: @fsub_fneg_nsz_p0_fnX_ebmaytrap(
367 ; CHECK-NEXT:    [[NEGA:%.*]] = fneg float [[A:%.*]]
368 ; CHECK-NEXT:    [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
369 ; CHECK-NEXT:    ret float [[RET]]
371   %nega = fneg float %a
372   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
373   ret float %ret
376 define float @fsub_fneg_nsz_nnan_p0_fnX_ebmaytrap(float %a) #0 {
377 ; CHECK-LABEL: @fsub_fneg_nsz_nnan_p0_fnX_ebmaytrap(
378 ; CHECK-NEXT:    ret float [[A:%.*]]
380   %nega = fneg float %a
381   %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
382   ret float %ret
385 ; Missing nnan: must not fire.
386 define float @fsub_fneg_nsz_p0_fnX_ebstrict(float %a) #0 {
387 ; CHECK-LABEL: @fsub_fneg_nsz_p0_fnX_ebstrict(
388 ; CHECK-NEXT:    [[NEGA:%.*]] = fneg float [[A:%.*]]
389 ; CHECK-NEXT:    [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
390 ; CHECK-NEXT:    ret float [[RET]]
392   %nega = fneg float %a
393   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
394   ret float %ret
397 ; The instruction is expected to remain, but the result isn't used.
398 define float @fsub_fneg_nnan_nsz_p0_fnX_ebstrict(float %a) #0 {
399 ; CHECK-LABEL: @fsub_fneg_nnan_nsz_p0_fnX_ebstrict(
400 ; CHECK-NEXT:    [[NEGA:%.*]] = fneg float [[A:%.*]]
401 ; CHECK-NEXT:    [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
402 ; CHECK-NEXT:    ret float [[A]]
404   %nega = fneg float %a
405   %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
406   ret float %ret
410 ; fsub 0.0, (fsub 0.0, X) ==> X if signed zeros are ignored.
413 ; TODO: Need constrained intrinsic support in m_FNeg() and m_FSub to fire.
414 define float @fsub_fsub_p0_nsz_fnX_defaultenv(float %a) #0 {
415 ; CHECK-LABEL: @fsub_fsub_p0_nsz_fnX_defaultenv(
416 ; CHECK-NEXT:    [[NEGA:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
417 ; CHECK-NEXT:    [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
418 ; CHECK-NEXT:    ret float [[RET]]
420   %nega = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore")
421   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore")
422   ret float %ret
425 ; Missing nnan: must not fire.
426 define float @fsub_fsub_nsz_p0_fnX_ebmaytrap(float %a) #0 {
427 ; CHECK-LABEL: @fsub_fsub_nsz_p0_fnX_ebmaytrap(
428 ; CHECK-NEXT:    [[NEGA:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
429 ; CHECK-NEXT:    [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
430 ; CHECK-NEXT:    ret float [[RET]]
432   %nega = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
433   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
434   ret float %ret
437 ; TODO: Need constrained intrinsic support in m_FNeg() and m_FSub to fire.
438 define float @fsub_fsub_nnan_nsz_p0_fnX_ebmaytrap(float %a) #0 {
439 ; CHECK-LABEL: @fsub_fsub_nnan_nsz_p0_fnX_ebmaytrap(
440 ; CHECK-NEXT:    [[NEGA:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
441 ; CHECK-NEXT:    [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
442 ; CHECK-NEXT:    ret float [[RET]]
444   %nega = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
445   %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
446   ret float %ret
449 ; Missing nnan: must not fire.
450 define float @fsub_fsub_nsz_p0_fnX_ebstrict(float %a) #0 {
451 ; CHECK-LABEL: @fsub_fsub_nsz_p0_fnX_ebstrict(
452 ; CHECK-NEXT:    [[NEGA:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
453 ; CHECK-NEXT:    [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
454 ; CHECK-NEXT:    ret float [[RET]]
456   %nega = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
457   %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
458   ret float %ret
461 ; TODO: Need constrained intrinsic support in m_FNeg() and m_FSub to fire.
462 define float @fsub_fsub_nnan_nsz_p0_fnX_ebstrict(float %a) #0 {
463 ; CHECK-LABEL: @fsub_fsub_nnan_nsz_p0_fnX_ebstrict(
464 ; CHECK-NEXT:    [[NEGA:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
465 ; CHECK-NEXT:    [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict")
466 ; CHECK-NEXT:    ret float [[RET]]
468   %nega = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
469   %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict")
470   ret float %ret
474 ; fsub nnan x, x ==> 0.0
477 ; Missing nnan: must not fire.
478 define float @fsub_x_x_defaultenv(float %a) #0 {
479 ; CHECK-LABEL: @fsub_x_x_defaultenv(
480 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
481 ; CHECK-NEXT:    ret float [[RET]]
483   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore")
484   ret float %ret
487 define float @fsub_nnan_x_x_defaultenv(float %a) #0 {
488 ; CHECK-LABEL: @fsub_nnan_x_x_defaultenv(
489 ; CHECK-NEXT:    ret float 0.000000e+00
491   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore")
492   ret float %ret
495 ; Missing nnan: must not fire.
496 define float @fsub_x_x_ebmaytrap(float %a) #0 {
497 ; CHECK-LABEL: @fsub_x_x_ebmaytrap(
498 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
499 ; CHECK-NEXT:    ret float [[RET]]
501   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
502   ret float %ret
505 ; TODO: This will fold if we allow non-default floating point environments.
506 define float @fsub_nnan_x_x_ebmaytrap(float %a) #0 {
507 ; CHECK-LABEL: @fsub_nnan_x_x_ebmaytrap(
508 ; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
509 ; CHECK-NEXT:    ret float [[RET]]
511   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
512   ret float %ret
515 ; Missing nnan: must not fire.
516 define float @fsub_x_x_ebstrict(float %a) #0 {
517 ; CHECK-LABEL: @fsub_x_x_ebstrict(
518 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.strict")
519 ; CHECK-NEXT:    ret float [[RET]]
521   %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
522   ret float %ret
525 ; TODO: This will fold if we allow non-default floating point environments.
526 ; The instruction is expected to remain, but the result isn't used.
527 define float @fsub_nnan_x_x_ebstrict(float %a) #0 {
528 ; CHECK-LABEL: @fsub_nnan_x_x_ebstrict(
529 ; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.strict")
530 ; CHECK-NEXT:    ret float [[RET]]
532   %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
533   ret float %ret
537 ; Y - (Y - X) --> X
540 ; Missing nsz and reassoc: must not fire
541 define float @fsub_fsub_y_x_x_defaultenv(float %x, float %y) #0 {
542 ; CHECK-LABEL: @fsub_fsub_y_x_x_defaultenv(
543 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
544 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
545 ; CHECK-NEXT:    ret float [[RET]]
547   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore")
548   %ret = call float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.ignore")
549   ret float %ret
552 ; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire.
553 define float @fsub_fsub_fmf_y_x_x_defaultenv(float %x, float %y) #0 {
554 ; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_defaultenv(
555 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
556 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
557 ; CHECK-NEXT:    ret float [[RET]]
559   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore")
560   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.ignore")
561   ret float %ret
564 ; TODO: Consider how alternate rounding modes can break these transforms.
566 ; The "fpexcept.maytrap" instruction must _not_ be folded into the
567 ; "fpexcept.ignore" instruction. This must not fire.
568 define float @fsub_fsub_fmf_y_x_x_ebmaytrap_defaultenv(float %x, float %y) #0 {
569 ; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_ebmaytrap_defaultenv(
570 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
571 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
572 ; CHECK-NEXT:    ret float [[RET]]
574   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
575   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.ignore")
576   ret float %ret
579 ; Missing nsz and reassoc: must not fire
580 define float @fsub_fsub_y_x_x_ebmaytrap(float %x, float %y) #0 {
581 ; CHECK-LABEL: @fsub_fsub_y_x_x_ebmaytrap(
582 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
583 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
584 ; CHECK-NEXT:    ret float [[RET]]
586   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
587   %ret = call float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
588   ret float %ret
591 ; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire.
592 define float @fsub_fsub_fmf_y_x_x_ebmaytrap(float %x, float %y) #0 {
593 ; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_ebmaytrap(
594 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
595 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
596 ; CHECK-NEXT:    ret float [[RET]]
598   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
599   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
600   ret float %ret
603 ; Missing nsz and reassoc: must not fire
604 define float @fsub_fsub_y_x_x_ebstrict(float %x, float %y) #0 {
605 ; CHECK-LABEL: @fsub_fsub_y_x_x_ebstrict(
606 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
607 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.strict")
608 ; CHECK-NEXT:    ret float [[RET]]
610   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.strict")
611   %ret = call float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.strict")
612   ret float %ret
615 ; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire.
616 define float @fsub_fsub_fmf_y_x_x_ebstrict(float %x, float %y) #0 {
617 ; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_ebstrict(
618 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
619 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.strict")
620 ; CHECK-NEXT:    ret float [[RET]]
622   %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.strict")
623   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.strict")
624   ret float %ret
628 ; (X + Y) - Y --> X
629 ; TODO: Missing IR matcher support means these won't fire.
632 ; Missing nsz and reassoc: must not fire
633 define float @fadd_fsub_x_y_y_defaultenv(float %x, float %y) #0 {
634 ; CHECK-LABEL: @fadd_fsub_x_y_y_defaultenv(
635 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
636 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
637 ; CHECK-NEXT:    ret float [[RET]]
639   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore")
640   %ret = call float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore")
641   ret float %ret
644 ; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire.
645 define float @fadd_fsub_fmf_x_y_y_defaultenv(float %x, float %y) #0 {
646 ; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_defaultenv(
647 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
648 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
649 ; CHECK-NEXT:    ret float [[RET]]
651   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore")
652   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore")
653   ret float %ret
656 ; The "fpexcept.maytrap" instruction must _not_ be folded into the
657 ; "fpexcept.ignore" instruction. This must not fire.
658 define float @fadd_fsub_fmf_x_y_y_ebmaytrap_defaultenv(float %x, float %y) #0 {
659 ; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_ebmaytrap_defaultenv(
660 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
661 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
662 ; CHECK-NEXT:    ret float [[RET]]
664   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
665   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore")
666   ret float %ret
669 ; Missing nsz and reassoc: must not fire
670 define float @fadd_fsub_x_y_y_ebmaytrap(float %x, float %y) #0 {
671 ; CHECK-LABEL: @fadd_fsub_x_y_y_ebmaytrap(
672 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
673 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
674 ; CHECK-NEXT:    ret float [[RET]]
676   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
677   %ret = call float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
678   ret float %ret
681 ; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire.
682 define float @fadd_fsub_fmf_x_y_y_ebmaytrap(float %x, float %y) #0 {
683 ; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_ebmaytrap(
684 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
685 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.maytrap")
686 ; CHECK-NEXT:    ret float [[RET]]
688   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
689   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
690   ret float %ret
693 ; Missing nsz and reassoc: must not fire
694 define float @fadd_fsub_x_y_y_ebstrict(float %x, float %y) #0 {
695 ; CHECK-LABEL: @fadd_fsub_x_y_y_ebstrict(
696 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
697 ; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.strict")
698 ; CHECK-NEXT:    ret float [[RET]]
700   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict")
701   %ret = call float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict")
702   ret float %ret
705 ; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire.
706 define float @fadd_fsub_fmf_x_y_y_ebstrict(float %x, float %y) #0 {
707 ; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_ebstrict(
708 ; CHECK-NEXT:    [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict")
709 ; CHECK-NEXT:    [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.strict")
710 ; CHECK-NEXT:    ret float [[RET]]
712   %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict")
713   %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict")
714   ret float %ret
717 declare float @llvm.fabs.f32(float)
718 declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
720 declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
721 declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata)
723 declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata)
725 attributes #0 = { strictfp }