1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -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
7
8define float @exact_inverse(float %x) {
9; CHECK-LABEL: @exact_inverse(
10; CHECK-NEXT:    [[DIV:%.*]] = fmul float [[X:%.*]], 1.250000e-01
11; CHECK-NEXT:    ret float [[DIV]]
12;
13  %div = fdiv float %x, 8.0
14  ret float %div
15}
16
17; Min normal float = 1.17549435E-38
18
19define float @exact_inverse2(float %x) {
20; CHECK-LABEL: @exact_inverse2(
21; CHECK-NEXT:    [[DIV:%.*]] = fmul float [[X:%.*]], 0x47D0000000000000
22; CHECK-NEXT:    ret float [[DIV]]
23;
24  %div = fdiv float %x, 0x3810000000000000
25  ret float %div
26}
27
28; Max exponent = 1.70141183E+38; don't transform to multiply with denormal.
29
30define float @exact_inverse_but_denorm(float %x) {
31; CHECK-LABEL: @exact_inverse_but_denorm(
32; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47E0000000000000
33; CHECK-NEXT:    ret float [[DIV]]
34;
35  %div = fdiv float %x, 0x47E0000000000000
36  ret float %div
37}
38
39; Denormal = float 1.40129846E-45; inverse can't be represented.
40
41define float @not_exact_inverse2(float %x) {
42; CHECK-LABEL: @not_exact_inverse2(
43; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], 0x36A0000000000000
44; CHECK-NEXT:    ret float [[DIV]]
45;
46  %div = fdiv float %x, 0x36A0000000000000
47  ret float %div
48}
49
50; Fast math allows us to replace this fdiv.
51
52define float @not_exact_but_allow_recip(float %x) {
53; CHECK-LABEL: @not_exact_but_allow_recip(
54; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp float [[X:%.*]], 0x3FD5555560000000
55; CHECK-NEXT:    ret float [[DIV]]
56;
57  %div = fdiv arcp float %x, 3.0
58  ret float %div
59}
60
61; Fast math allows us to replace this fdiv, but we don't to avoid a denormal.
62; TODO: What if the function attributes tell us that denormals are flushed?
63
64define float @not_exact_but_allow_recip_but_denorm(float %x) {
65; CHECK-LABEL: @not_exact_but_allow_recip_but_denorm(
66; CHECK-NEXT:    [[DIV:%.*]] = fdiv arcp float [[X:%.*]], 0x47E0000100000000
67; CHECK-NEXT:    ret float [[DIV]]
68;
69  %div = fdiv arcp float %x, 0x47E0000100000000
70  ret float %div
71}
72
73define <2 x float> @exact_inverse_splat(<2 x float> %x) {
74; CHECK-LABEL: @exact_inverse_splat(
75; CHECK-NEXT:    [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 2.500000e-01>
76; CHECK-NEXT:    ret <2 x float> [[DIV]]
77;
78  %div = fdiv <2 x float> %x, <float 4.0, float 4.0>
79  ret <2 x float> %div
80}
81
82; Fast math allows us to replace this fdiv.
83
84define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) {
85; CHECK-LABEL: @not_exact_but_allow_recip_splat(
86; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 0x3FD5555560000000, float 0x3FD5555560000000>
87; CHECK-NEXT:    ret <2 x float> [[DIV]]
88;
89  %div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0>
90  ret <2 x float> %div
91}
92
93define <2 x float> @exact_inverse_vec(<2 x float> %x) {
94; CHECK-LABEL: @exact_inverse_vec(
95; CHECK-NEXT:    [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 1.250000e-01>
96; CHECK-NEXT:    ret <2 x float> [[DIV]]
97;
98  %div = fdiv <2 x float> %x, <float 4.0, float 8.0>
99  ret <2 x float> %div
100}
101
102define <2 x float> @not_exact_inverse_splat(<2 x float> %x) {
103; CHECK-LABEL: @not_exact_inverse_splat(
104; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float 3.000000e+00>
105; CHECK-NEXT:    ret <2 x float> [[DIV]]
106;
107  %div = fdiv <2 x float> %x, <float 3.0, float 3.0>
108  ret <2 x float> %div
109}
110
111define <2 x float> @not_exact_inverse_vec(<2 x float> %x) {
112; CHECK-LABEL: @not_exact_inverse_vec(
113; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 3.000000e+00>
114; CHECK-NEXT:    ret <2 x float> [[DIV]]
115;
116  %div = fdiv <2 x float> %x, <float 4.0, float 3.0>
117  ret <2 x float> %div
118}
119
120define <2 x float> @not_exact_inverse_vec_arcp(<2 x float> %x) {
121; CHECK-LABEL: @not_exact_inverse_vec_arcp(
122; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 2.500000e-01, float 0x3FD5555560000000>
123; CHECK-NEXT:    ret <2 x float> [[DIV]]
124;
125  %div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0>
126  ret <2 x float> %div
127}
128
129define <2 x float> @not_exact_inverse_vec_arcp_with_undef_elt(<2 x float> %x) {
130; CHECK-LABEL: @not_exact_inverse_vec_arcp_with_undef_elt(
131; CHECK-NEXT:    [[DIV:%.*]] = fdiv arcp <2 x float> [[X:%.*]], <float undef, float 3.000000e+00>
132; CHECK-NEXT:    ret <2 x float> [[DIV]]
133;
134  %div = fdiv arcp <2 x float> %x, <float undef, float 3.0>
135  ret <2 x float> %div
136}
137
138; (X / Y) / Z --> X / (Y * Z)
139
140define float @div_with_div_numerator(float %x, float %y, float %z) {
141; CHECK-LABEL: @div_with_div_numerator(
142; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc arcp float [[Y:%.*]], [[Z:%.*]]
143; CHECK-NEXT:    [[DIV2:%.*]] = fdiv reassoc arcp float [[X:%.*]], [[TMP1]]
144; CHECK-NEXT:    ret float [[DIV2]]
145;
146  %div1 = fdiv ninf float %x, %y
147  %div2 = fdiv arcp reassoc float %div1, %z
148  ret float %div2
149}
150
151; Z / (X / Y) --> (Z * Y) / X
152
153define <2 x float> @div_with_div_denominator(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
154; CHECK-LABEL: @div_with_div_denominator(
155; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[Y:%.*]], [[Z:%.*]]
156; CHECK-NEXT:    [[DIV2:%.*]] = fdiv reassoc arcp <2 x float> [[TMP1]], [[X:%.*]]
157; CHECK-NEXT:    ret <2 x float> [[DIV2]]
158;
159  %div1 = fdiv nnan <2 x float> %x, %y
160  %div2 = fdiv arcp reassoc <2 x float> %z, %div1
161  ret <2 x float> %div2
162}
163
164; Don't create an extra multiply if we can't eliminate the first div.
165
166declare void @use_f32(float)
167
168define float @div_with_div_numerator_extra_use(float %x, float %y, float %z) {
169; CHECK-LABEL: @div_with_div_numerator_extra_use(
170; CHECK-NEXT:    [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
171; CHECK-NEXT:    [[DIV2:%.*]] = fdiv fast float [[DIV1]], [[Z:%.*]]
172; CHECK-NEXT:    call void @use_f32(float [[DIV1]])
173; CHECK-NEXT:    ret float [[DIV2]]
174;
175  %div1 = fdiv float %x, %y
176  %div2 = fdiv fast float %div1, %z
177  call void @use_f32(float %div1)
178  ret float %div2
179}
180
181define float @div_with_div_denominator_extra_use(float %x, float %y, float %z) {
182; CHECK-LABEL: @div_with_div_denominator_extra_use(
183; CHECK-NEXT:    [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
184; CHECK-NEXT:    [[DIV2:%.*]] = fdiv fast float [[Z:%.*]], [[DIV1]]
185; CHECK-NEXT:    call void @use_f32(float [[DIV1]])
186; CHECK-NEXT:    ret float [[DIV2]]
187;
188  %div1 = fdiv float %x, %y
189  %div2 = fdiv fast float %z, %div1
190  call void @use_f32(float %div1)
191  ret float %div2
192}
193
194; Z / (1.0 / Y) ==> Y * Z
195
196define float @div_with_div_denominator_with_one_as_numerator_extra_use(float %x, float %y, float %z) {
197; CHECK-LABEL: @div_with_div_denominator_with_one_as_numerator_extra_use(
198; CHECK-NEXT:    [[DIV1:%.*]] = fdiv float 1.000000e+00, [[Y:%.*]]
199; CHECK-NEXT:    [[DIV2:%.*]] = fmul reassoc arcp float [[Y]], [[Z:%.*]]
200; CHECK-NEXT:    call void @use_f32(float [[DIV1]])
201; CHECK-NEXT:    ret float [[DIV2]]
202;
203  %div1 = fdiv float 1.0, %y
204  %div2 = fdiv reassoc arcp float %z, %div1
205  call void @use_f32(float %div1)
206  ret float %div2
207}
208
209define float @fneg_fneg(float %x, float %y) {
210; CHECK-LABEL: @fneg_fneg(
211; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
212; CHECK-NEXT:    ret float [[DIV]]
213;
214  %x.fneg = fsub float -0.0, %x
215  %y.fneg = fsub float -0.0, %y
216  %div = fdiv float %x.fneg, %y.fneg
217  ret float %div
218}
219
220define float @unary_fneg_unary_fneg(float %x, float %y) {
221; CHECK-LABEL: @unary_fneg_unary_fneg(
222; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
223; CHECK-NEXT:    ret float [[DIV]]
224;
225  %x.fneg = fneg float %x
226  %y.fneg = fneg float %y
227  %div = fdiv float %x.fneg, %y.fneg
228  ret float %div
229}
230
231define float @unary_fneg_fneg(float %x, float %y) {
232; CHECK-LABEL: @unary_fneg_fneg(
233; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
234; CHECK-NEXT:    ret float [[DIV]]
235;
236  %x.fneg = fneg float %x
237  %y.fneg = fsub float -0.0, %y
238  %div = fdiv float %x.fneg, %y.fneg
239  ret float %div
240}
241
242define float @fneg_unary_fneg(float %x, float %y) {
243; CHECK-LABEL: @fneg_unary_fneg(
244; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
245; CHECK-NEXT:    ret float [[DIV]]
246;
247  %x.fneg = fsub float -0.0, %x
248  %y.fneg = fneg float %y
249  %div = fdiv float %x.fneg, %y.fneg
250  ret float %div
251}
252
253; The test above shows that no FMF are needed, but show that we are not dropping FMF.
254
255define float @fneg_fneg_fast(float %x, float %y) {
256; CHECK-LABEL: @fneg_fneg_fast(
257; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]]
258; CHECK-NEXT:    ret float [[DIV]]
259;
260  %x.fneg = fsub float -0.0, %x
261  %y.fneg = fsub float -0.0, %y
262  %div = fdiv fast float %x.fneg, %y.fneg
263  ret float %div
264}
265
266define float @unary_fneg_unary_fneg_fast(float %x, float %y) {
267; CHECK-LABEL: @unary_fneg_unary_fneg_fast(
268; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]]
269; CHECK-NEXT:    ret float [[DIV]]
270;
271  %x.fneg = fneg float %x
272  %y.fneg = fneg float %y
273  %div = fdiv fast float %x.fneg, %y.fneg
274  ret float %div
275}
276
277define <2 x float> @fneg_fneg_vec(<2 x float> %x, <2 x float> %y) {
278; CHECK-LABEL: @fneg_fneg_vec(
279; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
280; CHECK-NEXT:    ret <2 x float> [[DIV]]
281;
282  %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x
283  %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y
284  %div = fdiv <2 x float> %xneg, %yneg
285  ret <2 x float> %div
286}
287
288define <2 x float> @unary_fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) {
289; CHECK-LABEL: @unary_fneg_unary_fneg_vec(
290; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
291; CHECK-NEXT:    ret <2 x float> [[DIV]]
292;
293  %xneg = fneg <2 x float> %x
294  %yneg = fneg <2 x float> %y
295  %div = fdiv <2 x float> %xneg, %yneg
296  ret <2 x float> %div
297}
298
299define <2 x float> @fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) {
300; CHECK-LABEL: @fneg_unary_fneg_vec(
301; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
302; CHECK-NEXT:    ret <2 x float> [[DIV]]
303;
304  %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x
305  %yneg = fneg <2 x float> %y
306  %div = fdiv <2 x float> %xneg, %yneg
307  ret <2 x float> %div
308}
309
310define <2 x float> @unary_fneg_fneg_vec(<2 x float> %x, <2 x float> %y) {
311; CHECK-LABEL: @unary_fneg_fneg_vec(
312; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
313; CHECK-NEXT:    ret <2 x float> [[DIV]]
314;
315  %xneg = fneg <2 x float> %x
316  %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y
317  %div = fdiv <2 x float> %xneg, %yneg
318  ret <2 x float> %div
319}
320
321define <2 x float> @fneg_fneg_vec_undef_elts(<2 x float> %x, <2 x float> %y) {
322; CHECK-LABEL: @fneg_fneg_vec_undef_elts(
323; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
324; CHECK-NEXT:    ret <2 x float> [[DIV]]
325;
326  %xneg = fsub <2 x float> <float undef, float -0.0>, %x
327  %yneg = fsub <2 x float> <float -0.0, float undef>, %y
328  %div = fdiv <2 x float> %xneg, %yneg
329  ret <2 x float> %div
330}
331
332define float @fneg_dividend_constant_divisor(float %x) {
333; CHECK-LABEL: @fneg_dividend_constant_divisor(
334; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00
335; CHECK-NEXT:    ret float [[DIV]]
336;
337  %neg = fsub float -0.0, %x
338  %div = fdiv nsz float %neg, 3.0
339  ret  float %div
340}
341
342define float @unary_fneg_dividend_constant_divisor(float %x) {
343; CHECK-LABEL: @unary_fneg_dividend_constant_divisor(
344; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00
345; CHECK-NEXT:    ret float [[DIV]]
346;
347  %neg = fneg float %x
348  %div = fdiv nsz float %neg, 3.0
349  ret  float %div
350}
351
352define float @fneg_divisor_constant_dividend(float %x) {
353; CHECK-LABEL: @fneg_divisor_constant_dividend(
354; CHECK-NEXT:    [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]]
355; CHECK-NEXT:    ret float [[DIV]]
356;
357  %neg = fsub float -0.0, %x
358  %div = fdiv nnan float -3.0, %neg
359  ret float %div
360}
361
362define float @unary_fneg_divisor_constant_dividend(float %x) {
363; CHECK-LABEL: @unary_fneg_divisor_constant_dividend(
364; CHECK-NEXT:    [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]]
365; CHECK-NEXT:    ret float [[DIV]]
366;
367  %neg = fneg float %x
368  %div = fdiv nnan float -3.0, %neg
369  ret float %div
370}
371
372define <2 x float> @fneg_dividend_constant_divisor_vec(<2 x float> %x) {
373; CHECK-LABEL: @fneg_dividend_constant_divisor_vec(
374; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
375; CHECK-NEXT:    ret <2 x float> [[DIV]]
376;
377  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
378  %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
379  ret <2 x float> %div
380}
381
382define <2 x float> @unary_fneg_dividend_constant_divisor_vec(<2 x float> %x) {
383; CHECK-LABEL: @unary_fneg_dividend_constant_divisor_vec(
384; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
385; CHECK-NEXT:    ret <2 x float> [[DIV]]
386;
387  %neg = fneg <2 x float> %x
388  %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
389  ret <2 x float> %div
390}
391
392define <2 x float> @fneg_dividend_constant_divisor_vec_undef_elt(<2 x float> %x) {
393; CHECK-LABEL: @fneg_dividend_constant_divisor_vec_undef_elt(
394; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
395; CHECK-NEXT:    ret <2 x float> [[DIV]]
396;
397  %neg = fsub <2 x float> <float undef, float -0.0>, %x
398  %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
399  ret <2 x float> %div
400}
401
402define <2 x float> @fneg_divisor_constant_dividend_vec(<2 x float> %x) {
403; CHECK-LABEL: @fneg_divisor_constant_dividend_vec(
404; CHECK-NEXT:    [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]]
405; CHECK-NEXT:    ret <2 x float> [[DIV]]
406;
407  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
408  %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg
409  ret <2 x float> %div
410}
411
412define <2 x float> @unary_fneg_divisor_constant_dividend_vec(<2 x float> %x) {
413; CHECK-LABEL: @unary_fneg_divisor_constant_dividend_vec(
414; CHECK-NEXT:    [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]]
415; CHECK-NEXT:    ret <2 x float> [[DIV]]
416;
417  %neg = fneg <2 x float> %x
418  %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg
419  ret <2 x float> %div
420}
421
422
423; X / (X * Y) --> 1.0 / Y
424
425define float @div_factor(float %x, float %y) {
426; CHECK-LABEL: @div_factor(
427; CHECK-NEXT:    [[D:%.*]] = fdiv reassoc nnan float 1.000000e+00, [[Y:%.*]]
428; CHECK-NEXT:    ret float [[D]]
429;
430  %m = fmul float %x, %y
431  %d = fdiv nnan reassoc float %x, %m
432  ret float %d;
433}
434
435; We can't do the transform without 'nnan' because if x is NAN and y is a number, this should return NAN.
436
437define float @div_factor_too_strict(float %x, float %y) {
438; CHECK-LABEL: @div_factor_too_strict(
439; CHECK-NEXT:    [[M:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
440; CHECK-NEXT:    [[D:%.*]] = fdiv reassoc float [[X]], [[M]]
441; CHECK-NEXT:    ret float [[D]]
442;
443  %m = fmul float %x, %y
444  %d = fdiv reassoc float %x, %m
445  ret float %d
446}
447
448; Commute, verify vector types, and show that we are not dropping extra FMF.
449; X / (Y * X) --> 1.0 / Y
450
451define <2 x float> @div_factor_commute(<2 x float> %x, <2 x float> %y) {
452; CHECK-LABEL: @div_factor_commute(
453; CHECK-NEXT:    [[D:%.*]] = fdiv reassoc nnan ninf nsz <2 x float> <float 1.000000e+00, float 1.000000e+00>, [[Y:%.*]]
454; CHECK-NEXT:    ret <2 x float> [[D]]
455;
456  %m = fmul <2 x float> %y, %x
457  %d = fdiv nnan ninf nsz reassoc <2 x float> %x, %m
458  ret <2 x float> %d
459}
460
461; C1/(X*C2) => (C1/C2) / X
462
463define <2 x float> @div_constant_dividend1(<2 x float> %x) {
464; CHECK-LABEL: @div_constant_dividend1(
465; CHECK-NEXT:    [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 5.000000e+00, float 1.000000e+00>, [[X:%.*]]
466; CHECK-NEXT:    ret <2 x float> [[T2]]
467;
468  %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0>
469  %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float 7.0e0>, %t1
470  ret <2 x float> %t2
471}
472
473define <2 x float> @div_constant_dividend1_arcp_only(<2 x float> %x) {
474; CHECK-LABEL: @div_constant_dividend1_arcp_only(
475; CHECK-NEXT:    [[T1:%.*]] = fmul <2 x float> [[X:%.*]], <float 3.000000e+00, float 7.000000e+00>
476; CHECK-NEXT:    [[T2:%.*]] = fdiv arcp <2 x float> <float 1.500000e+01, float 7.000000e+00>, [[T1]]
477; CHECK-NEXT:    ret <2 x float> [[T2]]
478;
479  %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0>
480  %t2 = fdiv arcp <2 x float> <float 15.0e0, float 7.0e0>, %t1
481  ret <2 x float> %t2
482}
483
484; C1/(X/C2) => (C1*C2) / X
485
486define <2 x float> @div_constant_dividend2(<2 x float> %x) {
487; CHECK-LABEL: @div_constant_dividend2(
488; CHECK-NEXT:    [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 4.500000e+01, float 4.900000e+01>, [[X:%.*]]
489; CHECK-NEXT:    ret <2 x float> [[T2]]
490;
491  %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0>
492  %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
493  ret <2 x float> %t2
494}
495
496define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) {
497; CHECK-LABEL: @div_constant_dividend2_reassoc_only(
498; CHECK-NEXT:    [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float -7.000000e+00>
499; CHECK-NEXT:    [[T2:%.*]] = fdiv reassoc <2 x float> <float 1.500000e+01, float -7.000000e+00>, [[T1]]
500; CHECK-NEXT:    ret <2 x float> [[T2]]
501;
502  %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0>
503  %t2 = fdiv reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
504  ret <2 x float> %t2
505}
506
507; C1/(C2/X) => (C1/C2) * X
508; This tests the combination of 2 folds: (C1 * X) / C2 --> (C1 / C2) * X
509
510define <2 x float> @div_constant_dividend3(<2 x float> %x) {
511; CHECK-LABEL: @div_constant_dividend3(
512; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 1.500000e+01, float -7.000000e+00>
513; CHECK-NEXT:    [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 0x3FD5555560000000, float 0x3FC24924A0000000>
514; CHECK-NEXT:    ret <2 x float> [[T2]]
515;
516  %t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %x
517  %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
518  ret <2 x float> %t2
519}
520
521define double @fdiv_fneg1(double %x, double %y) {
522; CHECK-LABEL: @fdiv_fneg1(
523; CHECK-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
524; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
525; CHECK-NEXT:    ret double [[DIV]]
526;
527  %neg = fsub double -0.0, %x
528  %div = fdiv double %neg, %y
529  ret double %div
530}
531
532define double @fdiv_unary_fneg1(double %x, double %y) {
533; CHECK-LABEL: @fdiv_unary_fneg1(
534; CHECK-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
535; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
536; CHECK-NEXT:    ret double [[DIV]]
537;
538  %neg = fneg double %x
539  %div = fdiv double %neg, %y
540  ret double %div
541}
542
543define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) {
544; CHECK-LABEL: @fdiv_fneg2(
545; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
546; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
547; CHECK-NEXT:    ret <2 x float> [[DIV]]
548;
549  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
550  %div = fdiv <2 x float> %y, %neg
551  ret <2 x float> %div
552}
553
554define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) {
555; CHECK-LABEL: @fdiv_unary_fneg2(
556; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
557; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
558; CHECK-NEXT:    ret <2 x float> [[DIV]]
559;
560  %neg = fneg <2 x float> %x
561  %div = fdiv <2 x float> %y, %neg
562  ret <2 x float> %div
563}
564
565define float @fdiv_fneg1_extra_use(float %x, float %y) {
566; CHECK-LABEL: @fdiv_fneg1_extra_use(
567; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
568; CHECK-NEXT:    call void @use_f32(float [[NEG]])
569; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
570; CHECK-NEXT:    ret float [[DIV]]
571;
572  %neg = fsub float -0.0, %x
573  call void @use_f32(float %neg)
574  %div = fdiv float %neg, %y
575  ret float %div
576}
577
578define float @fabs_same_op(float %x) {
579; CHECK-LABEL: @fabs_same_op(
580; CHECK-NEXT:    [[R:%.*]] = fdiv float [[X:%.*]], [[X]]
581; CHECK-NEXT:    ret float [[R]]
582;
583  %a = call float @llvm.fabs.f32(float %x)
584  %r = fdiv float %a, %a
585  ret float %r
586}
587
588define float @fabs_same_op_extra_use(float %x) {
589; CHECK-LABEL: @fabs_same_op_extra_use(
590; CHECK-NEXT:    [[A:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
591; CHECK-NEXT:    call void @use_f32(float [[A]])
592; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc ninf float [[X]], [[X]]
593; CHECK-NEXT:    ret float [[R]]
594;
595  %a = call float @llvm.fabs.f32(float %x)
596  call void @use_f32(float %a)
597  %r = fdiv ninf reassoc float %a, %a
598  ret float %r
599}
600
601define float @fabs_fabs(float %x, float %y) {
602; CHECK-LABEL: @fabs_fabs(
603; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
604; CHECK-NEXT:    [[R:%.*]] = call float @llvm.fabs.f32(float [[TMP1]])
605; CHECK-NEXT:    ret float [[R]]
606;
607  %x.fabs = call float @llvm.fabs.f32(float %x)
608  %y.fabs = call float @llvm.fabs.f32(float %y)
609  %r = fdiv float %x.fabs, %y.fabs
610  ret float %r
611}
612
613define float @fabs_fabs_extra_use1(float %x, float %y) {
614; CHECK-LABEL: @fabs_fabs_extra_use1(
615; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
616; CHECK-NEXT:    call void @use_f32(float [[X_FABS]])
617; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf float [[X]], [[Y:%.*]]
618; CHECK-NEXT:    [[R:%.*]] = call ninf float @llvm.fabs.f32(float [[TMP1]])
619; CHECK-NEXT:    ret float [[R]]
620;
621  %x.fabs = call float @llvm.fabs.f32(float %x)
622  call void @use_f32(float %x.fabs)
623  %y.fabs = call float @llvm.fabs.f32(float %y)
624  %r = fdiv ninf float %x.fabs, %y.fabs
625  ret float %r
626}
627
628define float @fabs_fabs_extra_use2(float %x, float %y) {
629; CHECK-LABEL: @fabs_fabs_extra_use2(
630; CHECK-NEXT:    [[Y_FABS:%.*]] = call fast float @llvm.fabs.f32(float [[Y:%.*]])
631; CHECK-NEXT:    call void @use_f32(float [[Y_FABS]])
632; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc ninf float [[X:%.*]], [[Y]]
633; CHECK-NEXT:    [[R:%.*]] = call reassoc ninf float @llvm.fabs.f32(float [[TMP1]])
634; CHECK-NEXT:    ret float [[R]]
635;
636  %x.fabs = call fast float @llvm.fabs.f32(float %x)
637  %y.fabs = call fast float @llvm.fabs.f32(float %y)
638  call void @use_f32(float %y.fabs)
639  %r = fdiv reassoc ninf float %x.fabs, %y.fabs
640  ret float %r
641}
642
643; negative test - don't create an extra instruction
644
645define float @fabs_fabs_extra_use3(float %x, float %y) {
646; CHECK-LABEL: @fabs_fabs_extra_use3(
647; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
648; CHECK-NEXT:    call void @use_f32(float [[X_FABS]])
649; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
650; CHECK-NEXT:    call void @use_f32(float [[Y_FABS]])
651; CHECK-NEXT:    [[R:%.*]] = fdiv float [[X_FABS]], [[Y_FABS]]
652; CHECK-NEXT:    ret float [[R]]
653;
654  %x.fabs = call float @llvm.fabs.f32(float %x)
655  call void @use_f32(float %x.fabs)
656  %y.fabs = call float @llvm.fabs.f32(float %y)
657  call void @use_f32(float %y.fabs)
658  %r = fdiv float %x.fabs, %y.fabs
659  ret float %r
660}
661
662define float @pow_divisor(float %x, float %y, float %z) {
663; CHECK-LABEL: @pow_divisor(
664; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
665; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc arcp float @llvm.pow.f32(float [[X:%.*]], float [[TMP1]])
666; CHECK-NEXT:    [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]]
667; CHECK-NEXT:    ret float [[R]]
668;
669  %p = call float @llvm.pow.f32(float %x, float %y)
670  %r = fdiv reassoc arcp float %z, %p
671  ret float %r
672}
673
674; Negative test - don't create an extra pow
675
676define float @pow_divisor_extra_use(float %x, float %y, float %z) {
677; CHECK-LABEL: @pow_divisor_extra_use(
678; CHECK-NEXT:    [[P:%.*]] = call float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
679; CHECK-NEXT:    call void @use_f32(float [[P]])
680; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
681; CHECK-NEXT:    ret float [[R]]
682;
683  %p = call float @llvm.pow.f32(float %x, float %y)
684  call void @use_f32(float %p)
685  %r = fdiv reassoc arcp float %z, %p
686  ret float %r
687}
688
689; Negative test - must have reassoc+arcp
690
691define float @pow_divisor_not_enough_fmf(float %x, float %y, float %z) {
692; CHECK-LABEL: @pow_divisor_not_enough_fmf(
693; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
694; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
695; CHECK-NEXT:    ret float [[R]]
696;
697  %p = call fast float @llvm.pow.f32(float %x, float %y)
698  %r = fdiv reassoc float %z, %p
699  ret float %r
700}
701
702; Negative test - must have reassoc+arcp
703
704define float @pow_divisor_not_enough_fmf2(float %x, float %y, float %z) {
705; CHECK-LABEL: @pow_divisor_not_enough_fmf2(
706; CHECK-NEXT:    [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
707; CHECK-NEXT:    [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
708; CHECK-NEXT:    ret float [[R]]
709;
710  %p = call fast float @llvm.pow.f32(float %x, float %y)
711  %r = fdiv arcp float %z, %p
712  ret float %r
713}
714
715; Special-case - reciprocal does not require extra fmul
716
717define <2 x half> @pow_recip(<2 x half> %x, <2 x half> %y) {
718; CHECK-LABEL: @pow_recip(
719; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
720; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.pow.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]])
721; CHECK-NEXT:    ret <2 x half> [[TMP2]]
722;
723  %p = call <2 x half> @llvm.pow.v2f16(<2 x half> %x, <2 x half> %y)
724  %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
725  ret <2 x half> %r
726}
727