Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / fdiv.ll
blobc81a9ba6d4215d91c1cd298da9c22ecacd2cfe3b
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 declare float @llvm.fabs.f32(float) nounwind readnone
5 declare float @llvm.pow.f32(float, float) nounwind readnone
6 declare <2 x half> @llvm.pow.v2f16(<2 x half>, <2 x half>) nounwind readnone
7 declare float @llvm.exp.f32(float) nounwind readnone
8 declare <2 x half> @llvm.exp.v2f16(<2 x half>) nounwind readnone
9 declare float @llvm.exp2.f32(float) nounwind readnone
10 declare <2 x half> @llvm.exp2.v2f16(<2 x half>) nounwind readnone
11 declare float @llvm.powi.f32.i32(float, i32) nounwind readnone
12 declare <2 x half> @llvm.powi.v2f16.i32(<2 x half>, i32) nounwind readnone
14 define 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]]
19   %div = fdiv float %x, 8.0
20   ret float %div
23 ; Min normal float = 1.17549435E-38
25 define float @exact_inverse2(float %x) {
26 ; CHECK-LABEL: @exact_inverse2(
27 ; CHECK-NEXT:    [[DIV:%.*]] = fmul float [[X:%.*]], 0x47D0000000000000
28 ; CHECK-NEXT:    ret float [[DIV]]
30   %div = fdiv float %x, 0x3810000000000000
31   ret float %div
34 ; Max exponent = 1.70141183E+38; don't transform to multiply with denormal.
36 define 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]]
41   %div = fdiv float %x, 0x47E0000000000000
42   ret float %div
45 ; Denormal = float 1.40129846E-45; inverse can't be represented.
47 define 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]]
52   %div = fdiv float %x, 0x36A0000000000000
53   ret float %div
56 ; Fast math allows us to replace this fdiv.
58 define 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]]
63   %div = fdiv arcp float %x, 3.0
64   ret float %div
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?
70 define 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]]
75   %div = fdiv arcp float %x, 0x47E0000100000000
76   ret float %div
79 define <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]]
84   %div = fdiv <2 x float> %x, <float 4.0, float 4.0>
85   ret <2 x float> %div
88 define <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, i64 0), <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer)
91 ; CHECK-NEXT:    ret <vscale x 2 x float> [[DIV]]
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, i64 0), <vscale x 2 x float> undef, <vscale x 2 x i32> zeroinitializer)
94   ret <vscale x 2 x float> %div
97 ; Fast math allows us to replace this fdiv.
99 define <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]]
104   %div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0>
105   ret <2 x float> %div
108 define <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]]
113   %div = fdiv <2 x float> %x, <float 4.0, float 8.0>
114   ret <2 x float> %div
117 define <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]]
122   %div = fdiv <2 x float> %x, <float 3.0, float 3.0>
123   ret <2 x float> %div
126 define <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]]
131   %div = fdiv <2 x float> %x, <float 4.0, float 3.0>
132   ret <2 x float> %div
135 define <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]]
140   %div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0>
141   ret <2 x float> %div
144 define <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]]
149   %div = fdiv arcp <2 x float> %x, <float undef, float 3.0>
150   ret <2 x float> %div
153 ; (X / Y) / Z --> X / (Y * Z)
155 define 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]]
161   %div1 = fdiv ninf float %x, %y
162   %div2 = fdiv arcp reassoc float %div1, %z
163   ret float %div2
166 ; Z / (X / Y) --> (Z * Y) / X
168 define <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]]
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
179 ; Don't create an extra multiply if we can't eliminate the first div.
181 declare void @use_f32(float)
183 define 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]]
190   %div1 = fdiv float %x, %y
191   %div2 = fdiv fast float %div1, %z
192   call void @use_f32(float %div1)
193   ret float %div2
196 define 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]]
203   %div1 = fdiv float %x, %y
204   %div2 = fdiv fast float %z, %div1
205   call void @use_f32(float %div1)
206   ret float %div2
209 ; Z / (1.0 / Y) ==> Y * Z
211 define 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]]
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
224 define 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]]
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
235 define 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]]
240   %x.fneg = fneg float %x
241   %y.fneg = fneg float %y
242   %div = fdiv float %x.fneg, %y.fneg
243   ret float %div
246 define 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]]
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
257 define 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]]
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
268 ; The test above shows that no FMF are needed, but show that we are not dropping FMF.
270 define 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]]
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
281 define 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]]
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
292 define <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]]
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
303 define <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]]
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
314 define <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]]
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
325 define <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]]
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
336 define <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]]
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
347 define 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]]
352   %neg = fsub float -0.0, %x
353   %div = fdiv nsz float %neg, 3.0
354   ret  float %div
357 define 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]]
362   %neg = fneg float %x
363   %div = fdiv nsz float %neg, 3.0
364   ret  float %div
367 define 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]]
372   %neg = fsub float -0.0, %x
373   %div = fdiv nnan float -3.0, %neg
374   ret float %div
377 define 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]]
382   %neg = fneg float %x
383   %div = fdiv nnan float -3.0, %neg
384   ret float %div
387 define <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]]
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
397 define <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]]
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
407 define <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]]
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
417 define <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]]
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
427 define <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]]
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
438 ; X / (X * Y) --> 1.0 / Y
440 define 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]]
445   %m = fmul float %x, %y
446   %d = fdiv nnan reassoc float %x, %m
447   ret float %d;
450 ; We can't do the transform without 'nnan' because if x is NAN and y is a number, this should return NAN.
452 define 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]]
458   %m = fmul float %x, %y
459   %d = fdiv reassoc float %x, %m
460   ret float %d
463 ; Commute, verify vector types, and show that we are not dropping extra FMF.
464 ; X / (Y * X) --> 1.0 / Y
466 define <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]]
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
476 ; C1/(X*C2) => (C1/C2) / X
478 define <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]]
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
488 define <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]]
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
499 ; C1/(X/C2) => (C1*C2) / X
501 define <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]]
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
511 define <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]]
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
522 ; C1/(C2/X) => (C1/C2) * X
523 ; This tests the combination of 2 folds: (C1 * X) / C2 --> (C1 / C2) * X
525 define <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]]
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
536 define 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]]
542   %neg = fsub double -0.0, %x
543   %div = fdiv double %neg, %y
544   ret double %div
547 define 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]]
553   %neg = fneg double %x
554   %div = fdiv double %neg, %y
555   ret double %div
558 define <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]]
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
569 define <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]]
575   %neg = fneg <2 x float> %x
576   %div = fdiv <2 x float> %y, %neg
577   ret <2 x float> %div
580 define 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]]
587   %neg = fsub float -0.0, %x
588   call void @use_f32(float %neg)
589   %div = fdiv float %neg, %y
590   ret float %div
593 define 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]]
598   %a = call float @llvm.fabs.f32(float %x)
599   %r = fdiv float %a, %a
600   ret float %r
603 define 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]]
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
616 define 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]]
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
628 define 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]]
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
643 define 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]]
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
658 ; negative test - don't create an extra instruction
660 define 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]]
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
677 define 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]]
684   %p = call float @llvm.pow.f32(float %x, float %y)
685   %r = fdiv reassoc arcp float %z, %p
686   ret float %r
689 ; Negative test - don't create an extra pow
691 define 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]]
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
704 ; Negative test - must have reassoc+arcp
706 define 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]]
712   %p = call fast float @llvm.pow.f32(float %x, float %y)
713   %r = fdiv reassoc float %z, %p
714   ret float %r
717 ; Negative test - must have reassoc+arcp
719 define 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]]
725   %p = call fast float @llvm.pow.f32(float %x, float %y)
726   %r = fdiv arcp float %z, %p
727   ret float %r
730 ; Special-case - reciprocal does not require extra fmul
732 define <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]]
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
743 define 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]]
750   %p = call float @llvm.exp.f32(float %y)
751   %r = fdiv reassoc arcp float %z, %p
752   ret float %r
755 ; Negative test - don't create an extra exp
757 define 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]]
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
770 ; Negative test - must have reassoc+arcp
772 define 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]]
778   %p = call fast float @llvm.exp.f32(float %y)
779   %r = fdiv reassoc float %z, %p
780   ret float %r
783 ; Negative test - must have reassoc+arcp
785 define 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]]
791   %p = call fast float @llvm.exp.f32(float %y)
792   %r = fdiv arcp float %z, %p
793   ret float %r
796 ; Special-case - reciprocal does not require extra fmul
798 define <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]]
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
809 define 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]]
816   %p = call float @llvm.exp2.f32(float %y)
817   %r = fdiv reassoc arcp float %z, %p
818   ret float %r
821 ; Negative test - don't create an extra exp
823 define 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]]
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
836 ; Negative test - must have reassoc+arcp
838 define 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]]
844   %p = call fast float @llvm.exp2.f32(float %y)
845   %r = fdiv reassoc float %z, %p
846   ret float %r
849 ; Negative test - must have reassoc+arcp
851 define 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]]
857   %p = call fast float @llvm.exp2.f32(float %y)
858   %r = fdiv arcp float %z, %p
859   ret float %r
862 ; Special-case - reciprocal does not require extra fmul
864 define <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]]
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
875 define 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]]
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
887 ; Negative test - don't create an extra pow
889 define 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]]
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
902 ; Negative test - must have reassoc+arcp+ninf
904 define 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]]
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
915 ; Negative test - must have reassoc+arcp+ninf
917 define 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]]
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
928 ; Special-case - reciprocal does not require extra fmul
930 define <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]]
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
941 define float @fdiv_zero_f32(float %x) {
942 ; CHECK-LABEL: @fdiv_zero_f32(
943 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[X:%.*]], 0.000000e+00
944 ; CHECK-NEXT:    ret float [[FDIV]]
946   %fdiv = fdiv float %x, 0.0
947   ret float %fdiv
950 ; https://alive2.llvm.org/ce/z/gLBFKB
951 define float @fdiv_nnan_zero_f32(float %x) {
952 ; CHECK-LABEL: @fdiv_nnan_zero_f32(
953 ; CHECK-NEXT:    [[FDIV:%.*]] = call nnan float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]])
954 ; CHECK-NEXT:    ret float [[FDIV]]
956   %fdiv = fdiv nnan float %x, 0.0
957   ret float %fdiv
960 define <2 x float> @fdiv_nnan_zero_v2f32(<2 x float> %x) {
961 ; CHECK-LABEL: @fdiv_nnan_zero_v2f32(
962 ; CHECK-NEXT:    [[FDIV:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> [[X:%.*]])
963 ; CHECK-NEXT:    ret <2 x float> [[FDIV]]
965   %fdiv = fdiv nnan <2 x float> %x, zeroinitializer
966   ret <2 x float> %fdiv
969 define float @fdiv_nnan_zero_f32_fmf(float %x) {
970 ; CHECK-LABEL: @fdiv_nnan_zero_f32_fmf(
971 ; CHECK-NEXT:    [[FDIV:%.*]] = call nnan nsz float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]])
972 ; CHECK-NEXT:    ret float [[FDIV]]
974   %fdiv = fdiv nnan nsz float %x, 0.0
975   ret float %fdiv
978 define <2 x float> @fdiv_nnan_zero_v2f32_fmf(<2 x float> %x) {
979 ; CHECK-LABEL: @fdiv_nnan_zero_v2f32_fmf(
980 ; CHECK-NEXT:    [[FDIV:%.*]] = call nnan nsz <2 x float> @llvm.copysign.v2f32(<2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> [[X:%.*]])
981 ; CHECK-NEXT:    ret <2 x float> [[FDIV]]
983   %fdiv = fdiv nnan nsz <2 x float> %x, zeroinitializer
984   ret <2 x float> %fdiv
987 define float @fdiv_nnan_neg_zero_f32(float %x) {
988 ; CHECK-LABEL: @fdiv_nnan_neg_zero_f32(
989 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv nnan float [[X:%.*]], -0.000000e+00
990 ; CHECK-NEXT:    ret float [[FDIV]]
992   %fdiv = fdiv nnan float %x, -0.0
993   ret float %fdiv