xref: /llvm-project/llvm/test/Transforms/InstCombine/fdiv.ll (revision 02328e0465c256293950542f1a85eb55bcbc9d45)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3; RUN: opt -S -passes=instcombine -use-constant-fp-for-fixed-length-splat < %s | FileCheck %s
4
5declare float @llvm.fabs.f32(float) nounwind readnone
6declare float @llvm.pow.f32(float, float) nounwind readnone
7declare <2 x half> @llvm.pow.v2f16(<2 x half>, <2 x half>) nounwind readnone
8declare float @llvm.exp.f32(float) nounwind readnone
9declare <2 x half> @llvm.exp.v2f16(<2 x half>) nounwind readnone
10declare float @llvm.exp2.f32(float) nounwind readnone
11declare <2 x half> @llvm.exp2.v2f16(<2 x half>) nounwind readnone
12declare float @llvm.powi.f32.i32(float, i32) nounwind readnone
13declare <2 x half> @llvm.powi.v2f16.i32(<2 x half>, i32) nounwind readnone
14
15define float @exact_inverse(float %x) {
16; CHECK-LABEL: @exact_inverse(
17; CHECK-NEXT:    [[DIV:%.*]] = fmul float [[X:%.*]], 1.250000e-01
18; CHECK-NEXT:    ret float [[DIV]]
19;
20  %div = fdiv float %x, 8.0
21  ret float %div
22}
23
24; Min normal float = 1.17549435E-38
25
26define float @exact_inverse2(float %x) {
27; CHECK-LABEL: @exact_inverse2(
28; CHECK-NEXT:    [[DIV:%.*]] = fmul float [[X:%.*]], 0x47D0000000000000
29; CHECK-NEXT:    ret float [[DIV]]
30;
31  %div = fdiv float %x, 0x3810000000000000
32  ret float %div
33}
34
35; Max exponent = 1.70141183E+38; don't transform to multiply with denormal.
36
37define float @exact_inverse_but_denorm(float %x) {
38; CHECK-LABEL: @exact_inverse_but_denorm(
39; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47E0000000000000
40; CHECK-NEXT:    ret float [[DIV]]
41;
42  %div = fdiv float %x, 0x47E0000000000000
43  ret float %div
44}
45
46; Denormal = float 1.40129846E-45; inverse can't be represented.
47
48define float @not_exact_inverse2(float %x) {
49; CHECK-LABEL: @not_exact_inverse2(
50; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], 0x36A0000000000000
51; CHECK-NEXT:    ret float [[DIV]]
52;
53  %div = fdiv float %x, 0x36A0000000000000
54  ret float %div
55}
56
57; Fast math allows us to replace this fdiv.
58
59define float @not_exact_but_allow_recip(float %x) {
60; CHECK-LABEL: @not_exact_but_allow_recip(
61; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp float [[X:%.*]], 0x3FD5555560000000
62; CHECK-NEXT:    ret float [[DIV]]
63;
64  %div = fdiv arcp float %x, 3.0
65  ret float %div
66}
67
68; Fast math allows us to replace this fdiv, but we don't to avoid a denormal.
69; TODO: What if the function attributes tell us that denormals are flushed?
70
71define float @not_exact_but_allow_recip_but_denorm(float %x) {
72; CHECK-LABEL: @not_exact_but_allow_recip_but_denorm(
73; CHECK-NEXT:    [[DIV:%.*]] = fdiv arcp float [[X:%.*]], 0x47E0000100000000
74; CHECK-NEXT:    ret float [[DIV]]
75;
76  %div = fdiv arcp float %x, 0x47E0000100000000
77  ret float %div
78}
79
80define <2 x float> @exact_inverse_splat(<2 x float> %x) {
81; CHECK-LABEL: @exact_inverse_splat(
82; CHECK-NEXT:    [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], splat (float 2.500000e-01)
83; CHECK-NEXT:    ret <2 x float> [[DIV]]
84;
85  %div = fdiv <2 x float> %x, <float 4.0, float 4.0>
86  ret <2 x float> %div
87}
88
89define <vscale x 2 x float> @exact_inverse_scalable_splat(<vscale x 2 x float> %x) {
90; CHECK-LABEL: @exact_inverse_scalable_splat(
91; CHECK-NEXT:    [[DIV:%.*]] = fmul <vscale x 2 x float> [[X:%.*]], splat (float 2.500000e-01)
92; CHECK-NEXT:    ret <vscale x 2 x float> [[DIV]]
93;
94  %div = fdiv <vscale x 2 x float> %x, splat (float 4.0)
95  ret <vscale x 2 x float> %div
96}
97
98; Fast math allows us to replace this fdiv.
99
100define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) {
101; CHECK-LABEL: @not_exact_but_allow_recip_splat(
102; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], splat (float 0x3FD5555560000000)
103; CHECK-NEXT:    ret <2 x float> [[DIV]]
104;
105  %div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0>
106  ret <2 x float> %div
107}
108
109define <2 x float> @exact_inverse_vec(<2 x float> %x) {
110; CHECK-LABEL: @exact_inverse_vec(
111; CHECK-NEXT:    [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 1.250000e-01>
112; CHECK-NEXT:    ret <2 x float> [[DIV]]
113;
114  %div = fdiv <2 x float> %x, <float 4.0, float 8.0>
115  ret <2 x float> %div
116}
117
118define <2 x float> @not_exact_inverse_splat(<2 x float> %x) {
119; CHECK-LABEL: @not_exact_inverse_splat(
120; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], splat (float 3.000000e+00)
121; CHECK-NEXT:    ret <2 x float> [[DIV]]
122;
123  %div = fdiv <2 x float> %x, <float 3.0, float 3.0>
124  ret <2 x float> %div
125}
126
127define <2 x float> @not_exact_inverse_vec(<2 x float> %x) {
128; CHECK-LABEL: @not_exact_inverse_vec(
129; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 3.000000e+00>
130; CHECK-NEXT:    ret <2 x float> [[DIV]]
131;
132  %div = fdiv <2 x float> %x, <float 4.0, float 3.0>
133  ret <2 x float> %div
134}
135
136define <2 x float> @not_exact_inverse_vec_arcp(<2 x float> %x) {
137; CHECK-LABEL: @not_exact_inverse_vec_arcp(
138; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 2.500000e-01, float 0x3FD5555560000000>
139; CHECK-NEXT:    ret <2 x float> [[DIV]]
140;
141  %div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0>
142  ret <2 x float> %div
143}
144
145define <2 x float> @not_exact_inverse_vec_arcp_with_poison_elt(<2 x float> %x) {
146; CHECK-LABEL: @not_exact_inverse_vec_arcp_with_poison_elt(
147; CHECK-NEXT:    [[DIV:%.*]] = fdiv arcp <2 x float> [[X:%.*]], <float poison, float 3.000000e+00>
148; CHECK-NEXT:    ret <2 x float> [[DIV]]
149;
150  %div = fdiv arcp <2 x float> %x, <float poison, float 3.0>
151  ret <2 x float> %div
152}
153
154; (X / Y) / Z --> X / (Y * Z)
155
156define float @div_with_div_numerator(float %x, float %y, float %z) {
157; CHECK-LABEL: @div_with_div_numerator(
158; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc arcp float [[Y:%.*]], [[Z:%.*]]
159; CHECK-NEXT:    [[DIV2:%.*]] = fdiv reassoc arcp float [[X:%.*]], [[TMP1]]
160; CHECK-NEXT:    ret float [[DIV2]]
161;
162  %div1 = fdiv ninf float %x, %y
163  %div2 = fdiv arcp reassoc float %div1, %z
164  ret float %div2
165}
166
167; Z / (X / Y) --> (Z * Y) / X
168
169define <2 x float> @div_with_div_denominator(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
170; CHECK-LABEL: @div_with_div_denominator(
171; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[Y:%.*]], [[Z:%.*]]
172; CHECK-NEXT:    [[DIV2:%.*]] = fdiv reassoc arcp <2 x float> [[TMP1]], [[X:%.*]]
173; CHECK-NEXT:    ret <2 x float> [[DIV2]]
174;
175  %div1 = fdiv nnan <2 x float> %x, %y
176  %div2 = fdiv arcp reassoc <2 x float> %z, %div1
177  ret <2 x float> %div2
178}
179
180; Don't create an extra multiply if we can't eliminate the first div.
181
182declare void @use_f32(float)
183
184define float @div_with_div_numerator_extra_use(float %x, float %y, float %z) {
185; CHECK-LABEL: @div_with_div_numerator_extra_use(
186; CHECK-NEXT:    [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
187; CHECK-NEXT:    [[DIV2:%.*]] = fdiv fast float [[DIV1]], [[Z:%.*]]
188; CHECK-NEXT:    call void @use_f32(float [[DIV1]])
189; CHECK-NEXT:    ret float [[DIV2]]
190;
191  %div1 = fdiv float %x, %y
192  %div2 = fdiv fast float %div1, %z
193  call void @use_f32(float %div1)
194  ret float %div2
195}
196
197define float @div_with_div_denominator_extra_use(float %x, float %y, float %z) {
198; CHECK-LABEL: @div_with_div_denominator_extra_use(
199; CHECK-NEXT:    [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
200; CHECK-NEXT:    [[DIV2:%.*]] = fdiv fast float [[Z:%.*]], [[DIV1]]
201; CHECK-NEXT:    call void @use_f32(float [[DIV1]])
202; CHECK-NEXT:    ret float [[DIV2]]
203;
204  %div1 = fdiv float %x, %y
205  %div2 = fdiv fast float %z, %div1
206  call void @use_f32(float %div1)
207  ret float %div2
208}
209
210; Z / (1.0 / Y) ==> Y * Z
211
212define float @div_with_div_denominator_with_one_as_numerator_extra_use(float %x, float %y, float %z) {
213; CHECK-LABEL: @div_with_div_denominator_with_one_as_numerator_extra_use(
214; CHECK-NEXT:    [[DIV1:%.*]] = fdiv float 1.000000e+00, [[Y:%.*]]
215; CHECK-NEXT:    [[DIV2:%.*]] = fmul reassoc arcp float [[Y]], [[Z:%.*]]
216; CHECK-NEXT:    call void @use_f32(float [[DIV1]])
217; CHECK-NEXT:    ret float [[DIV2]]
218;
219  %div1 = fdiv float 1.0, %y
220  %div2 = fdiv reassoc arcp float %z, %div1
221  call void @use_f32(float %div1)
222  ret float %div2
223}
224
225define float @fneg_fneg(float %x, float %y) {
226; CHECK-LABEL: @fneg_fneg(
227; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
228; CHECK-NEXT:    ret float [[DIV]]
229;
230  %x.fneg = fsub float -0.0, %x
231  %y.fneg = fsub float -0.0, %y
232  %div = fdiv float %x.fneg, %y.fneg
233  ret float %div
234}
235
236define float @unary_fneg_unary_fneg(float %x, float %y) {
237; CHECK-LABEL: @unary_fneg_unary_fneg(
238; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
239; CHECK-NEXT:    ret float [[DIV]]
240;
241  %x.fneg = fneg float %x
242  %y.fneg = fneg float %y
243  %div = fdiv float %x.fneg, %y.fneg
244  ret float %div
245}
246
247define float @unary_fneg_fneg(float %x, float %y) {
248; CHECK-LABEL: @unary_fneg_fneg(
249; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
250; CHECK-NEXT:    ret float [[DIV]]
251;
252  %x.fneg = fneg float %x
253  %y.fneg = fsub float -0.0, %y
254  %div = fdiv float %x.fneg, %y.fneg
255  ret float %div
256}
257
258define float @fneg_unary_fneg(float %x, float %y) {
259; CHECK-LABEL: @fneg_unary_fneg(
260; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
261; CHECK-NEXT:    ret float [[DIV]]
262;
263  %x.fneg = fsub float -0.0, %x
264  %y.fneg = fneg float %y
265  %div = fdiv float %x.fneg, %y.fneg
266  ret float %div
267}
268
269; The test above shows that no FMF are needed, but show that we are not dropping FMF.
270
271define float @fneg_fneg_fast(float %x, float %y) {
272; CHECK-LABEL: @fneg_fneg_fast(
273; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]]
274; CHECK-NEXT:    ret float [[DIV]]
275;
276  %x.fneg = fsub float -0.0, %x
277  %y.fneg = fsub float -0.0, %y
278  %div = fdiv fast float %x.fneg, %y.fneg
279  ret float %div
280}
281
282define float @unary_fneg_unary_fneg_fast(float %x, float %y) {
283; CHECK-LABEL: @unary_fneg_unary_fneg_fast(
284; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]]
285; CHECK-NEXT:    ret float [[DIV]]
286;
287  %x.fneg = fneg float %x
288  %y.fneg = fneg float %y
289  %div = fdiv fast float %x.fneg, %y.fneg
290  ret float %div
291}
292
293define <2 x float> @fneg_fneg_vec(<2 x float> %x, <2 x float> %y) {
294; CHECK-LABEL: @fneg_fneg_vec(
295; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
296; CHECK-NEXT:    ret <2 x float> [[DIV]]
297;
298  %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x
299  %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y
300  %div = fdiv <2 x float> %xneg, %yneg
301  ret <2 x float> %div
302}
303
304define <2 x float> @unary_fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) {
305; CHECK-LABEL: @unary_fneg_unary_fneg_vec(
306; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
307; CHECK-NEXT:    ret <2 x float> [[DIV]]
308;
309  %xneg = fneg <2 x float> %x
310  %yneg = fneg <2 x float> %y
311  %div = fdiv <2 x float> %xneg, %yneg
312  ret <2 x float> %div
313}
314
315define <2 x float> @fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) {
316; CHECK-LABEL: @fneg_unary_fneg_vec(
317; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
318; CHECK-NEXT:    ret <2 x float> [[DIV]]
319;
320  %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x
321  %yneg = fneg <2 x float> %y
322  %div = fdiv <2 x float> %xneg, %yneg
323  ret <2 x float> %div
324}
325
326define <2 x float> @unary_fneg_fneg_vec(<2 x float> %x, <2 x float> %y) {
327; CHECK-LABEL: @unary_fneg_fneg_vec(
328; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
329; CHECK-NEXT:    ret <2 x float> [[DIV]]
330;
331  %xneg = fneg <2 x float> %x
332  %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y
333  %div = fdiv <2 x float> %xneg, %yneg
334  ret <2 x float> %div
335}
336
337define <2 x float> @fneg_fneg_vec_poison_elts(<2 x float> %x, <2 x float> %y) {
338; CHECK-LABEL: @fneg_fneg_vec_poison_elts(
339; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
340; CHECK-NEXT:    ret <2 x float> [[DIV]]
341;
342  %xneg = fsub <2 x float> <float poison, float -0.0>, %x
343  %yneg = fsub <2 x float> <float -0.0, float poison>, %y
344  %div = fdiv <2 x float> %xneg, %yneg
345  ret <2 x float> %div
346}
347
348define float @fneg_dividend_constant_divisor(float %x) {
349; CHECK-LABEL: @fneg_dividend_constant_divisor(
350; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00
351; CHECK-NEXT:    ret float [[DIV]]
352;
353  %neg = fsub float -0.0, %x
354  %div = fdiv nsz float %neg, 3.0
355  ret  float %div
356}
357
358define float @unary_fneg_dividend_constant_divisor(float %x) {
359; CHECK-LABEL: @unary_fneg_dividend_constant_divisor(
360; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00
361; CHECK-NEXT:    ret float [[DIV]]
362;
363  %neg = fneg float %x
364  %div = fdiv nsz float %neg, 3.0
365  ret  float %div
366}
367
368define float @fneg_divisor_constant_dividend(float %x) {
369; CHECK-LABEL: @fneg_divisor_constant_dividend(
370; CHECK-NEXT:    [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]]
371; CHECK-NEXT:    ret float [[DIV]]
372;
373  %neg = fsub float -0.0, %x
374  %div = fdiv nnan float -3.0, %neg
375  ret float %div
376}
377
378define float @unary_fneg_divisor_constant_dividend(float %x) {
379; CHECK-LABEL: @unary_fneg_divisor_constant_dividend(
380; CHECK-NEXT:    [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]]
381; CHECK-NEXT:    ret float [[DIV]]
382;
383  %neg = fneg float %x
384  %div = fdiv nnan float -3.0, %neg
385  ret float %div
386}
387
388define <2 x float> @fneg_dividend_constant_divisor_vec(<2 x float> %x) {
389; CHECK-LABEL: @fneg_dividend_constant_divisor_vec(
390; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
391; CHECK-NEXT:    ret <2 x float> [[DIV]]
392;
393  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
394  %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
395  ret <2 x float> %div
396}
397
398define <2 x float> @unary_fneg_dividend_constant_divisor_vec(<2 x float> %x) {
399; CHECK-LABEL: @unary_fneg_dividend_constant_divisor_vec(
400; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
401; CHECK-NEXT:    ret <2 x float> [[DIV]]
402;
403  %neg = fneg <2 x float> %x
404  %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
405  ret <2 x float> %div
406}
407
408define <2 x float> @fneg_dividend_constant_divisor_vec_poison_elt(<2 x float> %x) {
409; CHECK-LABEL: @fneg_dividend_constant_divisor_vec_poison_elt(
410; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
411; CHECK-NEXT:    ret <2 x float> [[DIV]]
412;
413  %neg = fsub <2 x float> <float poison, float -0.0>, %x
414  %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
415  ret <2 x float> %div
416}
417
418define <2 x float> @fneg_divisor_constant_dividend_vec(<2 x float> %x) {
419; CHECK-LABEL: @fneg_divisor_constant_dividend_vec(
420; CHECK-NEXT:    [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]]
421; CHECK-NEXT:    ret <2 x float> [[DIV]]
422;
423  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
424  %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg
425  ret <2 x float> %div
426}
427
428define <2 x float> @unary_fneg_divisor_constant_dividend_vec(<2 x float> %x) {
429; CHECK-LABEL: @unary_fneg_divisor_constant_dividend_vec(
430; CHECK-NEXT:    [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]]
431; CHECK-NEXT:    ret <2 x float> [[DIV]]
432;
433  %neg = fneg <2 x float> %x
434  %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg
435  ret <2 x float> %div
436}
437
438
439; X / (X * Y) --> 1.0 / Y
440
441define float @div_factor(float %x, float %y) {
442; CHECK-LABEL: @div_factor(
443; CHECK-NEXT:    [[D:%.*]] = fdiv reassoc nnan float 1.000000e+00, [[Y:%.*]]
444; CHECK-NEXT:    ret float [[D]]
445;
446  %m = fmul float %x, %y
447  %d = fdiv nnan reassoc float %x, %m
448  ret float %d;
449}
450
451; We can't do the transform without 'nnan' because if x is NAN and y is a number, this should return NAN.
452
453define float @div_factor_too_strict(float %x, float %y) {
454; CHECK-LABEL: @div_factor_too_strict(
455; CHECK-NEXT:    [[M:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
456; CHECK-NEXT:    [[D:%.*]] = fdiv reassoc float [[X]], [[M]]
457; CHECK-NEXT:    ret float [[D]]
458;
459  %m = fmul float %x, %y
460  %d = fdiv reassoc float %x, %m
461  ret float %d
462}
463
464; Commute, verify vector types, and show that we are not dropping extra FMF.
465; X / (Y * X) --> 1.0 / Y
466
467define <2 x float> @div_factor_commute(<2 x float> %x, <2 x float> %y) {
468; CHECK-LABEL: @div_factor_commute(
469; CHECK-NEXT:    [[D:%.*]] = fdiv reassoc nnan ninf nsz <2 x float> splat (float 1.000000e+00), [[Y:%.*]]
470; CHECK-NEXT:    ret <2 x float> [[D]]
471;
472  %m = fmul <2 x float> %y, %x
473  %d = fdiv nnan ninf nsz reassoc <2 x float> %x, %m
474  ret <2 x float> %d
475}
476
477; C1/(X*C2) => (C1/C2) / X
478
479define <2 x float> @div_constant_dividend1(<2 x float> %x) {
480; CHECK-LABEL: @div_constant_dividend1(
481; CHECK-NEXT:    [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 5.000000e+00, float 1.000000e+00>, [[X:%.*]]
482; CHECK-NEXT:    ret <2 x float> [[T2]]
483;
484  %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0>
485  %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float 7.0e0>, %t1
486  ret <2 x float> %t2
487}
488
489define <2 x float> @div_constant_dividend1_arcp_only(<2 x float> %x) {
490; CHECK-LABEL: @div_constant_dividend1_arcp_only(
491; CHECK-NEXT:    [[T1:%.*]] = fmul <2 x float> [[X:%.*]], <float 3.000000e+00, float 7.000000e+00>
492; CHECK-NEXT:    [[T2:%.*]] = fdiv arcp <2 x float> <float 1.500000e+01, float 7.000000e+00>, [[T1]]
493; CHECK-NEXT:    ret <2 x float> [[T2]]
494;
495  %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0>
496  %t2 = fdiv arcp <2 x float> <float 15.0e0, float 7.0e0>, %t1
497  ret <2 x float> %t2
498}
499
500; C1/(X/C2) => (C1*C2) / X
501
502define <2 x float> @div_constant_dividend2(<2 x float> %x) {
503; CHECK-LABEL: @div_constant_dividend2(
504; CHECK-NEXT:    [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 4.500000e+01, float 4.900000e+01>, [[X:%.*]]
505; CHECK-NEXT:    ret <2 x float> [[T2]]
506;
507  %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0>
508  %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
509  ret <2 x float> %t2
510}
511
512define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) {
513; CHECK-LABEL: @div_constant_dividend2_reassoc_only(
514; CHECK-NEXT:    [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float -7.000000e+00>
515; CHECK-NEXT:    [[T2:%.*]] = fdiv reassoc <2 x float> <float 1.500000e+01, float -7.000000e+00>, [[T1]]
516; CHECK-NEXT:    ret <2 x float> [[T2]]
517;
518  %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0>
519  %t2 = fdiv reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
520  ret <2 x float> %t2
521}
522
523; C1/(C2/X) => (C1/C2) * X
524; This tests the combination of 2 folds: (C1 * X) / C2 --> (C1 / C2) * X
525
526define <2 x float> @div_constant_dividend3(<2 x float> %x) {
527; CHECK-LABEL: @div_constant_dividend3(
528; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 1.500000e+01, float -7.000000e+00>
529; CHECK-NEXT:    [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 0x3FD5555560000000, float 0x3FC24924A0000000>
530; CHECK-NEXT:    ret <2 x float> [[T2]]
531;
532  %t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %x
533  %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
534  ret <2 x float> %t2
535}
536
537define double @fdiv_fneg1(double %x, double %y) {
538; CHECK-LABEL: @fdiv_fneg1(
539; CHECK-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
540; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
541; CHECK-NEXT:    ret double [[DIV]]
542;
543  %neg = fsub double -0.0, %x
544  %div = fdiv double %neg, %y
545  ret double %div
546}
547
548define double @fdiv_unary_fneg1(double %x, double %y) {
549; CHECK-LABEL: @fdiv_unary_fneg1(
550; CHECK-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
551; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
552; CHECK-NEXT:    ret double [[DIV]]
553;
554  %neg = fneg double %x
555  %div = fdiv double %neg, %y
556  ret double %div
557}
558
559define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) {
560; CHECK-LABEL: @fdiv_fneg2(
561; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
562; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
563; CHECK-NEXT:    ret <2 x float> [[DIV]]
564;
565  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
566  %div = fdiv <2 x float> %y, %neg
567  ret <2 x float> %div
568}
569
570define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) {
571; CHECK-LABEL: @fdiv_unary_fneg2(
572; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
573; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
574; CHECK-NEXT:    ret <2 x float> [[DIV]]
575;
576  %neg = fneg <2 x float> %x
577  %div = fdiv <2 x float> %y, %neg
578  ret <2 x float> %div
579}
580
581define float @fdiv_fneg1_extra_use(float %x, float %y) {
582; CHECK-LABEL: @fdiv_fneg1_extra_use(
583; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
584; CHECK-NEXT:    call void @use_f32(float [[NEG]])
585; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
586; CHECK-NEXT:    ret float [[DIV]]
587;
588  %neg = fsub float -0.0, %x
589  call void @use_f32(float %neg)
590  %div = fdiv float %neg, %y
591  ret float %div
592}
593
594define float @fabs_same_op(float %x) {
595; CHECK-LABEL: @fabs_same_op(
596; CHECK-NEXT:    [[R:%.*]] = fdiv float [[X:%.*]], [[X]]
597; CHECK-NEXT:    ret float [[R]]
598;
599  %a = call float @llvm.fabs.f32(float %x)
600  %r = fdiv float %a, %a
601  ret float %r
602}
603
604define float @fabs_same_op_extra_use(float %x) {
605; CHECK-LABEL: @fabs_same_op_extra_use(
606; CHECK-NEXT:    [[A:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
607; CHECK-NEXT:    call void @use_f32(float [[A]])
608; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc ninf float [[X]], [[X]]
609; CHECK-NEXT:    ret float [[R]]
610;
611  %a = call float @llvm.fabs.f32(float %x)
612  call void @use_f32(float %a)
613  %r = fdiv ninf reassoc float %a, %a
614  ret float %r
615}
616
617define float @fabs_fabs(float %x, float %y) {
618; CHECK-LABEL: @fabs_fabs(
619; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
620; CHECK-NEXT:    [[R:%.*]] = call float @llvm.fabs.f32(float [[TMP1]])
621; CHECK-NEXT:    ret float [[R]]
622;
623  %x.fabs = call float @llvm.fabs.f32(float %x)
624  %y.fabs = call float @llvm.fabs.f32(float %y)
625  %r = fdiv float %x.fabs, %y.fabs
626  ret float %r
627}
628
629define float @fabs_fabs_extra_use1(float %x, float %y) {
630; CHECK-LABEL: @fabs_fabs_extra_use1(
631; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
632; CHECK-NEXT:    call void @use_f32(float [[X_FABS]])
633; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf float [[X]], [[Y:%.*]]
634; CHECK-NEXT:    [[R:%.*]] = call ninf float @llvm.fabs.f32(float [[TMP1]])
635; CHECK-NEXT:    ret float [[R]]
636;
637  %x.fabs = call float @llvm.fabs.f32(float %x)
638  call void @use_f32(float %x.fabs)
639  %y.fabs = call float @llvm.fabs.f32(float %y)
640  %r = fdiv ninf float %x.fabs, %y.fabs
641  ret float %r
642}
643
644define float @fabs_fabs_extra_use2(float %x, float %y) {
645; CHECK-LABEL: @fabs_fabs_extra_use2(
646; CHECK-NEXT:    [[Y_FABS:%.*]] = call fast float @llvm.fabs.f32(float [[Y:%.*]])
647; CHECK-NEXT:    call void @use_f32(float [[Y_FABS]])
648; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc ninf float [[X:%.*]], [[Y]]
649; CHECK-NEXT:    [[R:%.*]] = call reassoc ninf float @llvm.fabs.f32(float [[TMP1]])
650; CHECK-NEXT:    ret float [[R]]
651;
652  %x.fabs = call fast float @llvm.fabs.f32(float %x)
653  %y.fabs = call fast float @llvm.fabs.f32(float %y)
654  call void @use_f32(float %y.fabs)
655  %r = fdiv reassoc ninf float %x.fabs, %y.fabs
656  ret float %r
657}
658
659; negative test - don't create an extra instruction
660
661define float @fabs_fabs_extra_use3(float %x, float %y) {
662; CHECK-LABEL: @fabs_fabs_extra_use3(
663; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
664; CHECK-NEXT:    call void @use_f32(float [[X_FABS]])
665; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
666; CHECK-NEXT:    call void @use_f32(float [[Y_FABS]])
667; CHECK-NEXT:    [[R:%.*]] = fdiv float [[X_FABS]], [[Y_FABS]]
668; CHECK-NEXT:    ret float [[R]]
669;
670  %x.fabs = call float @llvm.fabs.f32(float %x)
671  call void @use_f32(float %x.fabs)
672  %y.fabs = call float @llvm.fabs.f32(float %y)
673  call void @use_f32(float %y.fabs)
674  %r = fdiv float %x.fabs, %y.fabs
675  ret float %r
676}
677
678define float @pow_divisor(float %x, float %y, float %z) {
679; CHECK-LABEL: @pow_divisor(
680; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
681; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc arcp float @llvm.pow.f32(float [[X:%.*]], float [[TMP1]])
682; CHECK-NEXT:    [[R:%.*]] = fmul reassoc arcp float [[Z:%.*]], [[TMP2]]
683; CHECK-NEXT:    ret float [[R]]
684;
685  %p = call float @llvm.pow.f32(float %x, float %y)
686  %r = fdiv reassoc arcp float %z, %p
687  ret float %r
688}
689
690; Negative test - don't create an extra pow
691
692define float @pow_divisor_extra_use(float %x, float %y, float %z) {
693; CHECK-LABEL: @pow_divisor_extra_use(
694; CHECK-NEXT:    [[P:%.*]] = call float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
695; CHECK-NEXT:    call void @use_f32(float [[P]])
696; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
697; CHECK-NEXT:    ret float [[R]]
698;
699  %p = call float @llvm.pow.f32(float %x, float %y)
700  call void @use_f32(float %p)
701  %r = fdiv reassoc arcp float %z, %p
702  ret float %r
703}
704
705; Negative test - must have reassoc+arcp
706
707define float @pow_divisor_not_enough_fmf(float %x, float %y, float %z) {
708; CHECK-LABEL: @pow_divisor_not_enough_fmf(
709; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
710; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
711; CHECK-NEXT:    ret float [[R]]
712;
713  %p = call fast float @llvm.pow.f32(float %x, float %y)
714  %r = fdiv reassoc float %z, %p
715  ret float %r
716}
717
718; Negative test - must have reassoc+arcp
719
720define float @pow_divisor_not_enough_fmf2(float %x, float %y, float %z) {
721; CHECK-LABEL: @pow_divisor_not_enough_fmf2(
722; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
723; CHECK-NEXT:    [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
724; CHECK-NEXT:    ret float [[R]]
725;
726  %p = call fast float @llvm.pow.f32(float %x, float %y)
727  %r = fdiv arcp float %z, %p
728  ret float %r
729}
730
731; Special-case - reciprocal does not require extra fmul
732
733define <2 x half> @pow_recip(<2 x half> %x, <2 x half> %y) {
734; CHECK-LABEL: @pow_recip(
735; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
736; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.pow.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]])
737; CHECK-NEXT:    ret <2 x half> [[TMP2]]
738;
739  %p = call <2 x half> @llvm.pow.v2f16(<2 x half> %x, <2 x half> %y)
740  %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
741  ret <2 x half> %r
742}
743
744define float @exp_divisor(float %y, float %z) {
745; CHECK-LABEL: @exp_divisor(
746; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
747; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc arcp float @llvm.exp.f32(float [[TMP1]])
748; CHECK-NEXT:    [[R:%.*]] = fmul reassoc arcp float [[Z:%.*]], [[TMP2]]
749; CHECK-NEXT:    ret float [[R]]
750;
751  %p = call float @llvm.exp.f32(float %y)
752  %r = fdiv reassoc arcp float %z, %p
753  ret float %r
754}
755
756; Negative test - don't create an extra exp
757
758define float @exp_divisor_extra_use(float %y, float %z) {
759; CHECK-LABEL: @exp_divisor_extra_use(
760; CHECK-NEXT:    [[P:%.*]] = call float @llvm.exp.f32(float [[Y:%.*]])
761; CHECK-NEXT:    call void @use_f32(float [[P]])
762; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
763; CHECK-NEXT:    ret float [[R]]
764;
765  %p = call float @llvm.exp.f32(float %y)
766  call void @use_f32(float %p)
767  %r = fdiv reassoc arcp float %z, %p
768  ret float %r
769}
770
771; Negative test - must have reassoc+arcp
772
773define float @exp_divisor_not_enough_fmf(float %y, float %z) {
774; CHECK-LABEL: @exp_divisor_not_enough_fmf(
775; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.exp.f32(float [[Y:%.*]])
776; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
777; CHECK-NEXT:    ret float [[R]]
778;
779  %p = call fast float @llvm.exp.f32(float %y)
780  %r = fdiv reassoc float %z, %p
781  ret float %r
782}
783
784; Negative test - must have reassoc+arcp
785
786define float @exp_divisor_not_enough_fmf2(float %y, float %z) {
787; CHECK-LABEL: @exp_divisor_not_enough_fmf2(
788; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.exp.f32(float [[Y:%.*]])
789; CHECK-NEXT:    [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
790; CHECK-NEXT:    ret float [[R]]
791;
792  %p = call fast float @llvm.exp.f32(float %y)
793  %r = fdiv arcp float %z, %p
794  ret float %r
795}
796
797; Special-case - reciprocal does not require extra fmul
798
799define <2 x half> @exp_recip(<2 x half> %x, <2 x half> %y) {
800; CHECK-LABEL: @exp_recip(
801; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
802; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp.v2f16(<2 x half> [[TMP1]])
803; CHECK-NEXT:    ret <2 x half> [[TMP2]]
804;
805  %p = call <2 x half> @llvm.exp.v2f16(<2 x half> %y)
806  %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
807  ret <2 x half> %r
808}
809
810define float @exp2_divisor(float %y, float %z) {
811; CHECK-LABEL: @exp2_divisor(
812; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
813; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc arcp float @llvm.exp2.f32(float [[TMP1]])
814; CHECK-NEXT:    [[R:%.*]] = fmul reassoc arcp float [[Z:%.*]], [[TMP2]]
815; CHECK-NEXT:    ret float [[R]]
816;
817  %p = call float @llvm.exp2.f32(float %y)
818  %r = fdiv reassoc arcp float %z, %p
819  ret float %r
820}
821
822; Negative test - don't create an extra exp
823
824define float @exp2_divisor_extra_use(float %y, float %z) {
825; CHECK-LABEL: @exp2_divisor_extra_use(
826; CHECK-NEXT:    [[P:%.*]] = call float @llvm.exp2.f32(float [[Y:%.*]])
827; CHECK-NEXT:    call void @use_f32(float [[P]])
828; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
829; CHECK-NEXT:    ret float [[R]]
830;
831  %p = call float @llvm.exp2.f32(float %y)
832  call void @use_f32(float %p)
833  %r = fdiv reassoc arcp float %z, %p
834  ret float %r
835}
836
837; Negative test - must have reassoc+arcp
838
839define float @exp2_divisor_not_enough_fmf(float %y, float %z) {
840; CHECK-LABEL: @exp2_divisor_not_enough_fmf(
841; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.exp2.f32(float [[Y:%.*]])
842; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
843; CHECK-NEXT:    ret float [[R]]
844;
845  %p = call fast float @llvm.exp2.f32(float %y)
846  %r = fdiv reassoc float %z, %p
847  ret float %r
848}
849
850; Negative test - must have reassoc+arcp
851
852define float @exp2_divisor_not_enough_fmf2(float %y, float %z) {
853; CHECK-LABEL: @exp2_divisor_not_enough_fmf2(
854; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.exp2.f32(float [[Y:%.*]])
855; CHECK-NEXT:    [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
856; CHECK-NEXT:    ret float [[R]]
857;
858  %p = call fast float @llvm.exp2.f32(float %y)
859  %r = fdiv arcp float %z, %p
860  ret float %r
861}
862
863; Special-case - reciprocal does not require extra fmul
864
865define <2 x half> @exp2_recip(<2 x half> %x, <2 x half> %y) {
866; CHECK-LABEL: @exp2_recip(
867; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
868; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp2.v2f16(<2 x half> [[TMP1]])
869; CHECK-NEXT:    ret <2 x half> [[TMP2]]
870;
871  %p = call <2 x half> @llvm.exp2.v2f16(<2 x half> %y)
872  %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
873  ret <2 x half> %r
874}
875
876define float @powi_divisor(float %x, i32 %y, float %z) {
877; CHECK-LABEL: @powi_divisor(
878; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]
879; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc ninf arcp float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[TMP1]])
880; CHECK-NEXT:    [[R:%.*]] = fmul reassoc ninf arcp float [[Z:%.*]], [[TMP2]]
881; CHECK-NEXT:    ret float [[R]]
882;
883  %p = call float @llvm.powi.f32.i32(float %x, i32 %y)
884  %r = fdiv reassoc arcp ninf float %z, %p
885  ret float %r
886}
887
888; Negative test - don't create an extra pow
889
890define float @powi_divisor_extra_use(float %x, i32 %y, float %z) {
891; CHECK-LABEL: @powi_divisor_extra_use(
892; CHECK-NEXT:    [[P:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]])
893; CHECK-NEXT:    call void @use_f32(float [[P]])
894; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc ninf arcp float [[Z:%.*]], [[P]]
895; CHECK-NEXT:    ret float [[R]]
896;
897  %p = call float @llvm.powi.f32.i32(float %x, i32 %y)
898  call void @use_f32(float %p)
899  %r = fdiv reassoc arcp ninf float %z, %p
900  ret float %r
901}
902
903; Negative test - must have reassoc+arcp+ninf
904
905define float @powi_divisor_not_enough_fmf(float %x, i32 %y, float %z) {
906; CHECK-LABEL: @powi_divisor_not_enough_fmf(
907; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]])
908; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc ninf float [[Z:%.*]], [[P]]
909; CHECK-NEXT:    ret float [[R]]
910;
911  %p = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
912  %r = fdiv reassoc ninf float %z, %p
913  ret float %r
914}
915
916; Negative test - must have reassoc+arcp+ninf
917
918define float @powi_divisor_not_enough_fmf2(float %x, i32 %y, float %z) {
919; CHECK-LABEL: @powi_divisor_not_enough_fmf2(
920; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]])
921; CHECK-NEXT:    [[R:%.*]] = fdiv ninf arcp float [[Z:%.*]], [[P]]
922; CHECK-NEXT:    ret float [[R]]
923;
924  %p = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
925  %r = fdiv arcp ninf float %z, %p
926  ret float %r
927}
928
929; Special-case - reciprocal does not require extra fmul
930
931define <2 x half> @powi_recip(<2 x half> %x, i32 %y) {
932; CHECK-LABEL: @powi_recip(
933; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]
934; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc nnan ninf arcp <2 x half> @llvm.powi.v2f16.i32(<2 x half> [[X:%.*]], i32 [[TMP1]])
935; CHECK-NEXT:    ret <2 x half> [[TMP2]]
936;
937  %p = call <2 x half> @llvm.powi.v2f16.i32(<2 x half> %x, i32 %y)
938  %r = fdiv reassoc arcp nnan ninf <2 x half> <half 1.0, half 1.0>, %p
939  ret <2 x half> %r
940}
941
942define float @fdiv_zero_f32(float %x) {
943; CHECK-LABEL: @fdiv_zero_f32(
944; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[X:%.*]], 0.000000e+00
945; CHECK-NEXT:    ret float [[FDIV]]
946;
947  %fdiv = fdiv float %x, 0.0
948  ret float %fdiv
949}
950
951; https://alive2.llvm.org/ce/z/gLBFKB
952define float @fdiv_nnan_zero_f32(float %x) {
953; CHECK-LABEL: @fdiv_nnan_zero_f32(
954; CHECK-NEXT:    [[FDIV:%.*]] = call nnan float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]])
955; CHECK-NEXT:    ret float [[FDIV]]
956;
957  %fdiv = fdiv nnan float %x, 0.0
958  ret float %fdiv
959}
960
961define <2 x float> @fdiv_nnan_zero_v2f32(<2 x float> %x) {
962; CHECK-LABEL: @fdiv_nnan_zero_v2f32(
963; CHECK-NEXT:    [[FDIV:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> [[X:%.*]])
964; CHECK-NEXT:    ret <2 x float> [[FDIV]]
965;
966  %fdiv = fdiv nnan <2 x float> %x, zeroinitializer
967  ret <2 x float> %fdiv
968}
969
970define float @fdiv_nnan_zero_f32_fmf(float %x) {
971; CHECK-LABEL: @fdiv_nnan_zero_f32_fmf(
972; CHECK-NEXT:    [[FDIV:%.*]] = call nnan nsz float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]])
973; CHECK-NEXT:    ret float [[FDIV]]
974;
975  %fdiv = fdiv nnan nsz float %x, 0.0
976  ret float %fdiv
977}
978
979define <2 x float> @fdiv_nnan_zero_v2f32_fmf(<2 x float> %x) {
980; CHECK-LABEL: @fdiv_nnan_zero_v2f32_fmf(
981; CHECK-NEXT:    [[FDIV:%.*]] = call nnan nsz <2 x float> @llvm.copysign.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> [[X:%.*]])
982; CHECK-NEXT:    ret <2 x float> [[FDIV]]
983;
984  %fdiv = fdiv nnan nsz <2 x float> %x, zeroinitializer
985  ret <2 x float> %fdiv
986}
987
988define float @fdiv_nnan_neg_zero_f32(float %x) {
989; CHECK-LABEL: @fdiv_nnan_neg_zero_f32(
990; CHECK-NEXT:    [[FDIV:%.*]] = fdiv nnan float [[X:%.*]], -0.000000e+00
991; CHECK-NEXT:    ret float [[FDIV]]
992;
993  %fdiv = fdiv nnan float %x, -0.0
994  ret float %fdiv
995}
996
997define double @test_positive_zero_nsz(double %X) {
998; CHECK-LABEL: @test_positive_zero_nsz(
999; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]])
1000; CHECK-NEXT:    ret double [[TMP1]]
1001;
1002  %1 = fdiv nnan nsz double %X, 0.0
1003  ret double %1
1004}
1005
1006define double @test_negative_zero_nsz(double %X) {
1007; CHECK-LABEL: @test_negative_zero_nsz(
1008; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]])
1009; CHECK-NEXT:    ret double [[TMP1]]
1010;
1011  %1 = fdiv nnan nsz double %X, -0.0
1012  ret double %1
1013}
1014
1015define double @test_positive_zero(double %X) {
1016; CHECK-LABEL: @test_positive_zero(
1017; CHECK-NEXT:    [[TMP1:%.*]] = call nnan double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]])
1018; CHECK-NEXT:    ret double [[TMP1]]
1019;
1020  %1 = fdiv nnan double %X, 0.0
1021  ret double %1
1022}
1023
1024define double @test_negative_zero(double %X) {
1025; CHECK-LABEL: @test_negative_zero(
1026; CHECK-NEXT:    [[TMP1:%.*]] = fdiv nnan double [[X:%.*]], -0.000000e+00
1027; CHECK-NEXT:    ret double [[TMP1]]
1028;
1029  %1 = fdiv nnan double %X, -0.0
1030  ret double %1
1031}
1032
1033define <2 x double> @test_positive_zero_vector_nsz(<2 x double> %X) {
1034; CHECK-LABEL: @test_positive_zero_vector_nsz(
1035; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 0x7FF0000000000000), <2 x double> [[X:%.*]])
1036; CHECK-NEXT:    ret <2 x double> [[TMP1]]
1037;
1038  %1 = fdiv nnan nsz <2 x double> %X, <double 0.0, double 0.0>
1039  ret <2 x double> %1
1040}
1041
1042define <2 x double> @test_negative_zero_vector_nsz(<2 x double> %X) {
1043; CHECK-LABEL: @test_negative_zero_vector_nsz(
1044; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 0x7FF0000000000000), <2 x double> [[X:%.*]])
1045; CHECK-NEXT:    ret <2 x double> [[TMP1]]
1046;
1047  %1 = fdiv nnan nsz <2 x double> %X, <double -0.0, double 0.0>
1048  ret <2 x double> %1
1049}
1050
1051define <2 x double> @test_positive_zero_vector(<2 x double> %X) {
1052; CHECK-LABEL: @test_positive_zero_vector(
1053; CHECK-NEXT:    [[TMP1:%.*]] = call nnan <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 0x7FF0000000000000), <2 x double> [[X:%.*]])
1054; CHECK-NEXT:    ret <2 x double> [[TMP1]]
1055;
1056  %1 = fdiv nnan <2 x double> %X, <double 0.0, double 0.0>
1057  ret <2 x double> %1
1058}
1059
1060define <2 x double> @test_negative_zero_vector(<2 x double> %X) {
1061; CHECK-LABEL: @test_negative_zero_vector(
1062; CHECK-NEXT:    [[TMP1:%.*]] = fdiv nnan <2 x double> [[X:%.*]], <double -0.000000e+00, double 0.000000e+00>
1063; CHECK-NEXT:    ret <2 x double> [[TMP1]]
1064;
1065  %1 = fdiv nnan <2 x double> %X, <double -0.0, double 0.0>
1066  ret <2 x double> %1
1067}
1068