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