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