Files
clang-p2996/llvm/test/Transforms/InstCombine/fdiv.ll
Paul Walker fd07b8f809 [LLVM][tests/Transforms/InstCombine] Convert instances of ConstantExpr based splats to use splat().
This is mostly NFC but some output does change due to consistently
inserting into poison rather than undef and using i64 as the index
type for inserts.
2024-02-27 13:37:23 +00:00

1067 lines
37 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
declare float @llvm.fabs.f32(float) nounwind readnone
declare float @llvm.pow.f32(float, float) nounwind readnone
declare <2 x half> @llvm.pow.v2f16(<2 x half>, <2 x half>) nounwind readnone
declare float @llvm.exp.f32(float) nounwind readnone
declare <2 x half> @llvm.exp.v2f16(<2 x half>) nounwind readnone
declare float @llvm.exp2.f32(float) nounwind readnone
declare <2 x half> @llvm.exp2.v2f16(<2 x half>) nounwind readnone
declare float @llvm.powi.f32.i32(float, i32) nounwind readnone
declare <2 x half> @llvm.powi.v2f16.i32(<2 x half>, i32) nounwind readnone
define float @exact_inverse(float %x) {
; CHECK-LABEL: @exact_inverse(
; CHECK-NEXT: [[DIV:%.*]] = fmul float [[X:%.*]], 1.250000e-01
; CHECK-NEXT: ret float [[DIV]]
;
%div = fdiv float %x, 8.0
ret float %div
}
; Min normal float = 1.17549435E-38
define float @exact_inverse2(float %x) {
; CHECK-LABEL: @exact_inverse2(
; CHECK-NEXT: [[DIV:%.*]] = fmul float [[X:%.*]], 0x47D0000000000000
; CHECK-NEXT: ret float [[DIV]]
;
%div = fdiv float %x, 0x3810000000000000
ret float %div
}
; Max exponent = 1.70141183E+38; don't transform to multiply with denormal.
define float @exact_inverse_but_denorm(float %x) {
; CHECK-LABEL: @exact_inverse_but_denorm(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47E0000000000000
; CHECK-NEXT: ret float [[DIV]]
;
%div = fdiv float %x, 0x47E0000000000000
ret float %div
}
; Denormal = float 1.40129846E-45; inverse can't be represented.
define float @not_exact_inverse2(float %x) {
; CHECK-LABEL: @not_exact_inverse2(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x36A0000000000000
; CHECK-NEXT: ret float [[DIV]]
;
%div = fdiv float %x, 0x36A0000000000000
ret float %div
}
; Fast math allows us to replace this fdiv.
define float @not_exact_but_allow_recip(float %x) {
; CHECK-LABEL: @not_exact_but_allow_recip(
; CHECK-NEXT: [[DIV:%.*]] = fmul arcp float [[X:%.*]], 0x3FD5555560000000
; CHECK-NEXT: ret float [[DIV]]
;
%div = fdiv arcp float %x, 3.0
ret float %div
}
; Fast math allows us to replace this fdiv, but we don't to avoid a denormal.
; TODO: What if the function attributes tell us that denormals are flushed?
define float @not_exact_but_allow_recip_but_denorm(float %x) {
; CHECK-LABEL: @not_exact_but_allow_recip_but_denorm(
; CHECK-NEXT: [[DIV:%.*]] = fdiv arcp float [[X:%.*]], 0x47E0000100000000
; CHECK-NEXT: ret float [[DIV]]
;
%div = fdiv arcp float %x, 0x47E0000100000000
ret float %div
}
define <2 x float> @exact_inverse_splat(<2 x float> %x) {
; CHECK-LABEL: @exact_inverse_splat(
; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 2.500000e-01>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv <2 x float> %x, <float 4.0, float 4.0>
ret <2 x float> %div
}
define <vscale x 2 x float> @exact_inverse_scalable_splat(<vscale x 2 x float> %x) {
; CHECK-LABEL: @exact_inverse_scalable_splat(
; 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)
; CHECK-NEXT: ret <vscale x 2 x float> [[DIV]]
;
%div = fdiv <vscale x 2 x float> %x, splat (float 4.0)
ret <vscale x 2 x float> %div
}
; Fast math allows us to replace this fdiv.
define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) {
; CHECK-LABEL: @not_exact_but_allow_recip_splat(
; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 0x3FD5555560000000, float 0x3FD5555560000000>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0>
ret <2 x float> %div
}
define <2 x float> @exact_inverse_vec(<2 x float> %x) {
; CHECK-LABEL: @exact_inverse_vec(
; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 1.250000e-01>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv <2 x float> %x, <float 4.0, float 8.0>
ret <2 x float> %div
}
define <2 x float> @not_exact_inverse_splat(<2 x float> %x) {
; CHECK-LABEL: @not_exact_inverse_splat(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float 3.000000e+00>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv <2 x float> %x, <float 3.0, float 3.0>
ret <2 x float> %div
}
define <2 x float> @not_exact_inverse_vec(<2 x float> %x) {
; CHECK-LABEL: @not_exact_inverse_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 3.000000e+00>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv <2 x float> %x, <float 4.0, float 3.0>
ret <2 x float> %div
}
define <2 x float> @not_exact_inverse_vec_arcp(<2 x float> %x) {
; CHECK-LABEL: @not_exact_inverse_vec_arcp(
; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 2.500000e-01, float 0x3FD5555560000000>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0>
ret <2 x float> %div
}
define <2 x float> @not_exact_inverse_vec_arcp_with_undef_elt(<2 x float> %x) {
; CHECK-LABEL: @not_exact_inverse_vec_arcp_with_undef_elt(
; CHECK-NEXT: [[DIV:%.*]] = fdiv arcp <2 x float> [[X:%.*]], <float undef, float 3.000000e+00>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%div = fdiv arcp <2 x float> %x, <float undef, float 3.0>
ret <2 x float> %div
}
; (X / Y) / Z --> X / (Y * Z)
define float @div_with_div_numerator(float %x, float %y, float %z) {
; CHECK-LABEL: @div_with_div_numerator(
; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp float [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv reassoc arcp float [[X:%.*]], [[TMP1]]
; CHECK-NEXT: ret float [[DIV2]]
;
%div1 = fdiv ninf float %x, %y
%div2 = fdiv arcp reassoc float %div1, %z
ret float %div2
}
; Z / (X / Y) --> (Z * Y) / X
define <2 x float> @div_with_div_denominator(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
; CHECK-LABEL: @div_with_div_denominator(
; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv reassoc arcp <2 x float> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV2]]
;
%div1 = fdiv nnan <2 x float> %x, %y
%div2 = fdiv arcp reassoc <2 x float> %z, %div1
ret <2 x float> %div2
}
; Don't create an extra multiply if we can't eliminate the first div.
declare void @use_f32(float)
define float @div_with_div_numerator_extra_use(float %x, float %y, float %z) {
; CHECK-LABEL: @div_with_div_numerator_extra_use(
; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv fast float [[DIV1]], [[Z:%.*]]
; CHECK-NEXT: call void @use_f32(float [[DIV1]])
; CHECK-NEXT: ret float [[DIV2]]
;
%div1 = fdiv float %x, %y
%div2 = fdiv fast float %div1, %z
call void @use_f32(float %div1)
ret float %div2
}
define float @div_with_div_denominator_extra_use(float %x, float %y, float %z) {
; CHECK-LABEL: @div_with_div_denominator_extra_use(
; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv fast float [[Z:%.*]], [[DIV1]]
; CHECK-NEXT: call void @use_f32(float [[DIV1]])
; CHECK-NEXT: ret float [[DIV2]]
;
%div1 = fdiv float %x, %y
%div2 = fdiv fast float %z, %div1
call void @use_f32(float %div1)
ret float %div2
}
; Z / (1.0 / Y) ==> Y * Z
define float @div_with_div_denominator_with_one_as_numerator_extra_use(float %x, float %y, float %z) {
; CHECK-LABEL: @div_with_div_denominator_with_one_as_numerator_extra_use(
; CHECK-NEXT: [[DIV1:%.*]] = fdiv float 1.000000e+00, [[Y:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fmul reassoc arcp float [[Y]], [[Z:%.*]]
; CHECK-NEXT: call void @use_f32(float [[DIV1]])
; CHECK-NEXT: ret float [[DIV2]]
;
%div1 = fdiv float 1.0, %y
%div2 = fdiv reassoc arcp float %z, %div1
call void @use_f32(float %div1)
ret float %div2
}
define float @fneg_fneg(float %x, float %y) {
; CHECK-LABEL: @fneg_fneg(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%x.fneg = fsub float -0.0, %x
%y.fneg = fsub float -0.0, %y
%div = fdiv float %x.fneg, %y.fneg
ret float %div
}
define float @unary_fneg_unary_fneg(float %x, float %y) {
; CHECK-LABEL: @unary_fneg_unary_fneg(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%x.fneg = fneg float %x
%y.fneg = fneg float %y
%div = fdiv float %x.fneg, %y.fneg
ret float %div
}
define float @unary_fneg_fneg(float %x, float %y) {
; CHECK-LABEL: @unary_fneg_fneg(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%x.fneg = fneg float %x
%y.fneg = fsub float -0.0, %y
%div = fdiv float %x.fneg, %y.fneg
ret float %div
}
define float @fneg_unary_fneg(float %x, float %y) {
; CHECK-LABEL: @fneg_unary_fneg(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%x.fneg = fsub float -0.0, %x
%y.fneg = fneg float %y
%div = fdiv float %x.fneg, %y.fneg
ret float %div
}
; The test above shows that no FMF are needed, but show that we are not dropping FMF.
define float @fneg_fneg_fast(float %x, float %y) {
; CHECK-LABEL: @fneg_fneg_fast(
; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%x.fneg = fsub float -0.0, %x
%y.fneg = fsub float -0.0, %y
%div = fdiv fast float %x.fneg, %y.fneg
ret float %div
}
define float @unary_fneg_unary_fneg_fast(float %x, float %y) {
; CHECK-LABEL: @unary_fneg_unary_fneg_fast(
; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%x.fneg = fneg float %x
%y.fneg = fneg float %y
%div = fdiv fast float %x.fneg, %y.fneg
ret float %div
}
define <2 x float> @fneg_fneg_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_fneg_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%xneg = fsub <2 x float> <float -0.0, float -0.0>, %x
%yneg = fsub <2 x float> <float -0.0, float -0.0>, %y
%div = fdiv <2 x float> %xneg, %yneg
ret <2 x float> %div
}
define <2 x float> @unary_fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @unary_fneg_unary_fneg_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%xneg = fneg <2 x float> %x
%yneg = fneg <2 x float> %y
%div = fdiv <2 x float> %xneg, %yneg
ret <2 x float> %div
}
define <2 x float> @fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_unary_fneg_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%xneg = fsub <2 x float> <float -0.0, float -0.0>, %x
%yneg = fneg <2 x float> %y
%div = fdiv <2 x float> %xneg, %yneg
ret <2 x float> %div
}
define <2 x float> @unary_fneg_fneg_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @unary_fneg_fneg_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%xneg = fneg <2 x float> %x
%yneg = fsub <2 x float> <float -0.0, float -0.0>, %y
%div = fdiv <2 x float> %xneg, %yneg
ret <2 x float> %div
}
define <2 x float> @fneg_fneg_vec_undef_elts(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_fneg_vec_undef_elts(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%xneg = fsub <2 x float> <float undef, float -0.0>, %x
%yneg = fsub <2 x float> <float -0.0, float undef>, %y
%div = fdiv <2 x float> %xneg, %yneg
ret <2 x float> %div
}
define float @fneg_dividend_constant_divisor(float %x) {
; CHECK-LABEL: @fneg_dividend_constant_divisor(
; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00
; CHECK-NEXT: ret float [[DIV]]
;
%neg = fsub float -0.0, %x
%div = fdiv nsz float %neg, 3.0
ret float %div
}
define float @unary_fneg_dividend_constant_divisor(float %x) {
; CHECK-LABEL: @unary_fneg_dividend_constant_divisor(
; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00
; CHECK-NEXT: ret float [[DIV]]
;
%neg = fneg float %x
%div = fdiv nsz float %neg, 3.0
ret float %div
}
define float @fneg_divisor_constant_dividend(float %x) {
; CHECK-LABEL: @fneg_divisor_constant_dividend(
; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%neg = fsub float -0.0, %x
%div = fdiv nnan float -3.0, %neg
ret float %div
}
define float @unary_fneg_divisor_constant_dividend(float %x) {
; CHECK-LABEL: @unary_fneg_divisor_constant_dividend(
; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%neg = fneg float %x
%div = fdiv nnan float -3.0, %neg
ret float %div
}
define <2 x float> @fneg_dividend_constant_divisor_vec(<2 x float> %x) {
; CHECK-LABEL: @fneg_dividend_constant_divisor_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
%div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
ret <2 x float> %div
}
define <2 x float> @unary_fneg_dividend_constant_divisor_vec(<2 x float> %x) {
; CHECK-LABEL: @unary_fneg_dividend_constant_divisor_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fneg <2 x float> %x
%div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
ret <2 x float> %div
}
define <2 x float> @fneg_dividend_constant_divisor_vec_undef_elt(<2 x float> %x) {
; CHECK-LABEL: @fneg_dividend_constant_divisor_vec_undef_elt(
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00>
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fsub <2 x float> <float undef, float -0.0>, %x
%div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0>
ret <2 x float> %div
}
define <2 x float> @fneg_divisor_constant_dividend_vec(<2 x float> %x) {
; CHECK-LABEL: @fneg_divisor_constant_dividend_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
%div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg
ret <2 x float> %div
}
define <2 x float> @unary_fneg_divisor_constant_dividend_vec(<2 x float> %x) {
; CHECK-LABEL: @unary_fneg_divisor_constant_dividend_vec(
; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fneg <2 x float> %x
%div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg
ret <2 x float> %div
}
; X / (X * Y) --> 1.0 / Y
define float @div_factor(float %x, float %y) {
; CHECK-LABEL: @div_factor(
; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan float 1.000000e+00, [[Y:%.*]]
; CHECK-NEXT: ret float [[D]]
;
%m = fmul float %x, %y
%d = fdiv nnan reassoc float %x, %m
ret float %d;
}
; We can't do the transform without 'nnan' because if x is NAN and y is a number, this should return NAN.
define float @div_factor_too_strict(float %x, float %y) {
; CHECK-LABEL: @div_factor_too_strict(
; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[D:%.*]] = fdiv reassoc float [[X]], [[M]]
; CHECK-NEXT: ret float [[D]]
;
%m = fmul float %x, %y
%d = fdiv reassoc float %x, %m
ret float %d
}
; Commute, verify vector types, and show that we are not dropping extra FMF.
; X / (Y * X) --> 1.0 / Y
define <2 x float> @div_factor_commute(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @div_factor_commute(
; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan ninf nsz <2 x float> <float 1.000000e+00, float 1.000000e+00>, [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[D]]
;
%m = fmul <2 x float> %y, %x
%d = fdiv nnan ninf nsz reassoc <2 x float> %x, %m
ret <2 x float> %d
}
; C1/(X*C2) => (C1/C2) / X
define <2 x float> @div_constant_dividend1(<2 x float> %x) {
; CHECK-LABEL: @div_constant_dividend1(
; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 5.000000e+00, float 1.000000e+00>, [[X:%.*]]
; CHECK-NEXT: ret <2 x float> [[T2]]
;
%t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0>
%t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float 7.0e0>, %t1
ret <2 x float> %t2
}
define <2 x float> @div_constant_dividend1_arcp_only(<2 x float> %x) {
; CHECK-LABEL: @div_constant_dividend1_arcp_only(
; CHECK-NEXT: [[T1:%.*]] = fmul <2 x float> [[X:%.*]], <float 3.000000e+00, float 7.000000e+00>
; CHECK-NEXT: [[T2:%.*]] = fdiv arcp <2 x float> <float 1.500000e+01, float 7.000000e+00>, [[T1]]
; CHECK-NEXT: ret <2 x float> [[T2]]
;
%t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0>
%t2 = fdiv arcp <2 x float> <float 15.0e0, float 7.0e0>, %t1
ret <2 x float> %t2
}
; C1/(X/C2) => (C1*C2) / X
define <2 x float> @div_constant_dividend2(<2 x float> %x) {
; CHECK-LABEL: @div_constant_dividend2(
; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 4.500000e+01, float 4.900000e+01>, [[X:%.*]]
; CHECK-NEXT: ret <2 x float> [[T2]]
;
%t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0>
%t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
ret <2 x float> %t2
}
define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) {
; CHECK-LABEL: @div_constant_dividend2_reassoc_only(
; CHECK-NEXT: [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float -7.000000e+00>
; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc <2 x float> <float 1.500000e+01, float -7.000000e+00>, [[T1]]
; CHECK-NEXT: ret <2 x float> [[T2]]
;
%t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0>
%t2 = fdiv reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
ret <2 x float> %t2
}
; C1/(C2/X) => (C1/C2) * X
; This tests the combination of 2 folds: (C1 * X) / C2 --> (C1 / C2) * X
define <2 x float> @div_constant_dividend3(<2 x float> %x) {
; CHECK-LABEL: @div_constant_dividend3(
; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 1.500000e+01, float -7.000000e+00>
; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 0x3FD5555560000000, float 0x3FC24924A0000000>
; CHECK-NEXT: ret <2 x float> [[T2]]
;
%t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %x
%t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1
ret <2 x float> %t2
}
define double @fdiv_fneg1(double %x, double %y) {
; CHECK-LABEL: @fdiv_fneg1(
; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
; CHECK-NEXT: ret double [[DIV]]
;
%neg = fsub double -0.0, %x
%div = fdiv double %neg, %y
ret double %div
}
define double @fdiv_unary_fneg1(double %x, double %y) {
; CHECK-LABEL: @fdiv_unary_fneg1(
; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
; CHECK-NEXT: ret double [[DIV]]
;
%neg = fneg double %x
%div = fdiv double %neg, %y
ret double %div
}
define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fdiv_fneg2(
; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
%div = fdiv <2 x float> %y, %neg
ret <2 x float> %div
}
define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fdiv_unary_fneg2(
; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
; CHECK-NEXT: ret <2 x float> [[DIV]]
;
%neg = fneg <2 x float> %x
%div = fdiv <2 x float> %y, %neg
ret <2 x float> %div
}
define float @fdiv_fneg1_extra_use(float %x, float %y) {
; CHECK-LABEL: @fdiv_fneg1_extra_use(
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use_f32(float [[NEG]])
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
; CHECK-NEXT: ret float [[DIV]]
;
%neg = fsub float -0.0, %x
call void @use_f32(float %neg)
%div = fdiv float %neg, %y
ret float %div
}
define float @fabs_same_op(float %x) {
; CHECK-LABEL: @fabs_same_op(
; CHECK-NEXT: [[R:%.*]] = fdiv float [[X:%.*]], [[X]]
; CHECK-NEXT: ret float [[R]]
;
%a = call float @llvm.fabs.f32(float %x)
%r = fdiv float %a, %a
ret float %r
}
define float @fabs_same_op_extra_use(float %x) {
; CHECK-LABEL: @fabs_same_op_extra_use(
; CHECK-NEXT: [[A:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: call void @use_f32(float [[A]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf float [[X]], [[X]]
; CHECK-NEXT: ret float [[R]]
;
%a = call float @llvm.fabs.f32(float %x)
call void @use_f32(float %a)
%r = fdiv ninf reassoc float %a, %a
ret float %r
}
define float @fabs_fabs(float %x, float %y) {
; CHECK-LABEL: @fabs_fabs(
; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[TMP1]])
; CHECK-NEXT: ret float [[R]]
;
%x.fabs = call float @llvm.fabs.f32(float %x)
%y.fabs = call float @llvm.fabs.f32(float %y)
%r = fdiv float %x.fabs, %y.fabs
ret float %r
}
define float @fabs_fabs_extra_use1(float %x, float %y) {
; CHECK-LABEL: @fabs_fabs_extra_use1(
; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: call void @use_f32(float [[X_FABS]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv ninf float [[X]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.fabs.f32(float [[TMP1]])
; CHECK-NEXT: ret float [[R]]
;
%x.fabs = call float @llvm.fabs.f32(float %x)
call void @use_f32(float %x.fabs)
%y.fabs = call float @llvm.fabs.f32(float %y)
%r = fdiv ninf float %x.fabs, %y.fabs
ret float %r
}
define float @fabs_fabs_extra_use2(float %x, float %y) {
; CHECK-LABEL: @fabs_fabs_extra_use2(
; CHECK-NEXT: [[Y_FABS:%.*]] = call fast float @llvm.fabs.f32(float [[Y:%.*]])
; CHECK-NEXT: call void @use_f32(float [[Y_FABS]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv reassoc ninf float [[X:%.*]], [[Y]]
; CHECK-NEXT: [[R:%.*]] = call reassoc ninf float @llvm.fabs.f32(float [[TMP1]])
; CHECK-NEXT: ret float [[R]]
;
%x.fabs = call fast float @llvm.fabs.f32(float %x)
%y.fabs = call fast float @llvm.fabs.f32(float %y)
call void @use_f32(float %y.fabs)
%r = fdiv reassoc ninf float %x.fabs, %y.fabs
ret float %r
}
; negative test - don't create an extra instruction
define float @fabs_fabs_extra_use3(float %x, float %y) {
; CHECK-LABEL: @fabs_fabs_extra_use3(
; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: call void @use_f32(float [[X_FABS]])
; CHECK-NEXT: [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
; CHECK-NEXT: call void @use_f32(float [[Y_FABS]])
; CHECK-NEXT: [[R:%.*]] = fdiv float [[X_FABS]], [[Y_FABS]]
; CHECK-NEXT: ret float [[R]]
;
%x.fabs = call float @llvm.fabs.f32(float %x)
call void @use_f32(float %x.fabs)
%y.fabs = call float @llvm.fabs.f32(float %y)
call void @use_f32(float %y.fabs)
%r = fdiv float %x.fabs, %y.fabs
ret float %r
}
define float @pow_divisor(float %x, float %y, float %z) {
; CHECK-LABEL: @pow_divisor(
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.pow.f32(float [[X:%.*]], float [[TMP1]])
; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.pow.f32(float %x, float %y)
%r = fdiv reassoc arcp float %z, %p
ret float %r
}
; Negative test - don't create an extra pow
define float @pow_divisor_extra_use(float %x, float %y, float %z) {
; CHECK-LABEL: @pow_divisor_extra_use(
; CHECK-NEXT: [[P:%.*]] = call float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
; CHECK-NEXT: call void @use_f32(float [[P]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.pow.f32(float %x, float %y)
call void @use_f32(float %p)
%r = fdiv reassoc arcp float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp
define float @pow_divisor_not_enough_fmf(float %x, float %y, float %z) {
; CHECK-LABEL: @pow_divisor_not_enough_fmf(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.pow.f32(float %x, float %y)
%r = fdiv reassoc float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp
define float @pow_divisor_not_enough_fmf2(float %x, float %y, float %z) {
; CHECK-LABEL: @pow_divisor_not_enough_fmf2(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.pow.f32(float %x, float %y)
%r = fdiv arcp float %z, %p
ret float %r
}
; Special-case - reciprocal does not require extra fmul
define <2 x half> @pow_recip(<2 x half> %x, <2 x half> %y) {
; CHECK-LABEL: @pow_recip(
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.pow.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]])
; CHECK-NEXT: ret <2 x half> [[TMP2]]
;
%p = call <2 x half> @llvm.pow.v2f16(<2 x half> %x, <2 x half> %y)
%r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
ret <2 x half> %r
}
define float @exp_divisor(float %y, float %z) {
; CHECK-LABEL: @exp_divisor(
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.exp.f32(float [[TMP1]])
; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.exp.f32(float %y)
%r = fdiv reassoc arcp float %z, %p
ret float %r
}
; Negative test - don't create an extra exp
define float @exp_divisor_extra_use(float %y, float %z) {
; CHECK-LABEL: @exp_divisor_extra_use(
; CHECK-NEXT: [[P:%.*]] = call float @llvm.exp.f32(float [[Y:%.*]])
; CHECK-NEXT: call void @use_f32(float [[P]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.exp.f32(float %y)
call void @use_f32(float %p)
%r = fdiv reassoc arcp float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp
define float @exp_divisor_not_enough_fmf(float %y, float %z) {
; CHECK-LABEL: @exp_divisor_not_enough_fmf(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp.f32(float [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.exp.f32(float %y)
%r = fdiv reassoc float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp
define float @exp_divisor_not_enough_fmf2(float %y, float %z) {
; CHECK-LABEL: @exp_divisor_not_enough_fmf2(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp.f32(float [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.exp.f32(float %y)
%r = fdiv arcp float %z, %p
ret float %r
}
; Special-case - reciprocal does not require extra fmul
define <2 x half> @exp_recip(<2 x half> %x, <2 x half> %y) {
; CHECK-LABEL: @exp_recip(
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp.v2f16(<2 x half> [[TMP1]])
; CHECK-NEXT: ret <2 x half> [[TMP2]]
;
%p = call <2 x half> @llvm.exp.v2f16(<2 x half> %y)
%r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
ret <2 x half> %r
}
define float @exp2_divisor(float %y, float %z) {
; CHECK-LABEL: @exp2_divisor(
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.exp2.f32(float [[TMP1]])
; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.exp2.f32(float %y)
%r = fdiv reassoc arcp float %z, %p
ret float %r
}
; Negative test - don't create an extra exp
define float @exp2_divisor_extra_use(float %y, float %z) {
; CHECK-LABEL: @exp2_divisor_extra_use(
; CHECK-NEXT: [[P:%.*]] = call float @llvm.exp2.f32(float [[Y:%.*]])
; CHECK-NEXT: call void @use_f32(float [[P]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.exp2.f32(float %y)
call void @use_f32(float %p)
%r = fdiv reassoc arcp float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp
define float @exp2_divisor_not_enough_fmf(float %y, float %z) {
; CHECK-LABEL: @exp2_divisor_not_enough_fmf(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp2.f32(float [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.exp2.f32(float %y)
%r = fdiv reassoc float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp
define float @exp2_divisor_not_enough_fmf2(float %y, float %z) {
; CHECK-LABEL: @exp2_divisor_not_enough_fmf2(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp2.f32(float [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.exp2.f32(float %y)
%r = fdiv arcp float %z, %p
ret float %r
}
; Special-case - reciprocal does not require extra fmul
define <2 x half> @exp2_recip(<2 x half> %x, <2 x half> %y) {
; CHECK-LABEL: @exp2_recip(
; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp2.v2f16(<2 x half> [[TMP1]])
; CHECK-NEXT: ret <2 x half> [[TMP2]]
;
%p = call <2 x half> @llvm.exp2.v2f16(<2 x half> %y)
%r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p
ret <2 x half> %r
}
define float @powi_divisor(float %x, i32 %y, float %z) {
; CHECK-LABEL: @powi_divisor(
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[TMP1]])
; CHECK-NEXT: [[R:%.*]] = fmul reassoc ninf arcp float [[TMP2]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.powi.f32.i32(float %x, i32 %y)
%r = fdiv reassoc arcp ninf float %z, %p
ret float %r
}
; Negative test - don't create an extra pow
define float @powi_divisor_extra_use(float %x, i32 %y, float %z) {
; CHECK-LABEL: @powi_divisor_extra_use(
; CHECK-NEXT: [[P:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: call void @use_f32(float [[P]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call float @llvm.powi.f32.i32(float %x, i32 %y)
call void @use_f32(float %p)
%r = fdiv reassoc arcp ninf float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp+ninf
define float @powi_divisor_not_enough_fmf(float %x, i32 %y, float %z) {
; CHECK-LABEL: @powi_divisor_not_enough_fmf(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
%r = fdiv reassoc ninf float %z, %p
ret float %r
}
; Negative test - must have reassoc+arcp+ninf
define float @powi_divisor_not_enough_fmf2(float %x, i32 %y, float %z) {
; CHECK-LABEL: @powi_divisor_not_enough_fmf2(
; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: [[R:%.*]] = fdiv ninf arcp float [[Z:%.*]], [[P]]
; CHECK-NEXT: ret float [[R]]
;
%p = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
%r = fdiv arcp ninf float %z, %p
ret float %r
}
; Special-case - reciprocal does not require extra fmul
define <2 x half> @powi_recip(<2 x half> %x, i32 %y) {
; CHECK-LABEL: @powi_recip(
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc nnan ninf arcp <2 x half> @llvm.powi.v2f16.i32(<2 x half> [[X:%.*]], i32 [[TMP1]])
; CHECK-NEXT: ret <2 x half> [[TMP2]]
;
%p = call <2 x half> @llvm.powi.v2f16.i32(<2 x half> %x, i32 %y)
%r = fdiv reassoc arcp nnan ninf <2 x half> <half 1.0, half 1.0>, %p
ret <2 x half> %r
}
define float @fdiv_zero_f32(float %x) {
; CHECK-LABEL: @fdiv_zero_f32(
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret float [[FDIV]]
;
%fdiv = fdiv float %x, 0.0
ret float %fdiv
}
; https://alive2.llvm.org/ce/z/gLBFKB
define float @fdiv_nnan_zero_f32(float %x) {
; CHECK-LABEL: @fdiv_nnan_zero_f32(
; CHECK-NEXT: [[FDIV:%.*]] = call nnan float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]])
; CHECK-NEXT: ret float [[FDIV]]
;
%fdiv = fdiv nnan float %x, 0.0
ret float %fdiv
}
define <2 x float> @fdiv_nnan_zero_v2f32(<2 x float> %x) {
; CHECK-LABEL: @fdiv_nnan_zero_v2f32(
; CHECK-NEXT: [[FDIV:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> [[X:%.*]])
; CHECK-NEXT: ret <2 x float> [[FDIV]]
;
%fdiv = fdiv nnan <2 x float> %x, zeroinitializer
ret <2 x float> %fdiv
}
define float @fdiv_nnan_zero_f32_fmf(float %x) {
; CHECK-LABEL: @fdiv_nnan_zero_f32_fmf(
; CHECK-NEXT: [[FDIV:%.*]] = call nnan nsz float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]])
; CHECK-NEXT: ret float [[FDIV]]
;
%fdiv = fdiv nnan nsz float %x, 0.0
ret float %fdiv
}
define <2 x float> @fdiv_nnan_zero_v2f32_fmf(<2 x float> %x) {
; CHECK-LABEL: @fdiv_nnan_zero_v2f32_fmf(
; CHECK-NEXT: [[FDIV:%.*]] = call nnan nsz <2 x float> @llvm.copysign.v2f32(<2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> [[X:%.*]])
; CHECK-NEXT: ret <2 x float> [[FDIV]]
;
%fdiv = fdiv nnan nsz <2 x float> %x, zeroinitializer
ret <2 x float> %fdiv
}
define float @fdiv_nnan_neg_zero_f32(float %x) {
; CHECK-LABEL: @fdiv_nnan_neg_zero_f32(
; CHECK-NEXT: [[FDIV:%.*]] = fdiv nnan float [[X:%.*]], -0.000000e+00
; CHECK-NEXT: ret float [[FDIV]]
;
%fdiv = fdiv nnan float %x, -0.0
ret float %fdiv
}
define double @test_positive_zero_nsz(double %X) {
; CHECK-LABEL: @test_positive_zero_nsz(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]])
; CHECK-NEXT: ret double [[TMP1]]
;
%1 = fdiv nnan nsz double %X, 0.0
ret double %1
}
define double @test_negative_zero_nsz(double %X) {
; CHECK-LABEL: @test_negative_zero_nsz(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]])
; CHECK-NEXT: ret double [[TMP1]]
;
%1 = fdiv nnan nsz double %X, -0.0
ret double %1
}
define double @test_positive_zero(double %X) {
; CHECK-LABEL: @test_positive_zero(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]])
; CHECK-NEXT: ret double [[TMP1]]
;
%1 = fdiv nnan double %X, 0.0
ret double %1
}
define double @test_negative_zero(double %X) {
; CHECK-LABEL: @test_negative_zero(
; CHECK-NEXT: [[TMP1:%.*]] = fdiv nnan double [[X:%.*]], -0.000000e+00
; CHECK-NEXT: ret double [[TMP1]]
;
%1 = fdiv nnan double %X, -0.0
ret double %1
}
define <2 x double> @test_positive_zero_vector_nsz(<2 x double> %X) {
; CHECK-LABEL: @test_positive_zero_vector_nsz(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <2 x double> @llvm.copysign.v2f64(<2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>, <2 x double> [[X:%.*]])
; CHECK-NEXT: ret <2 x double> [[TMP1]]
;
%1 = fdiv nnan nsz <2 x double> %X, <double 0.0, double 0.0>
ret <2 x double> %1
}
define <2 x double> @test_negative_zero_vector_nsz(<2 x double> %X) {
; CHECK-LABEL: @test_negative_zero_vector_nsz(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <2 x double> @llvm.copysign.v2f64(<2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>, <2 x double> [[X:%.*]])
; CHECK-NEXT: ret <2 x double> [[TMP1]]
;
%1 = fdiv nnan nsz <2 x double> %X, <double -0.0, double 0.0>
ret <2 x double> %1
}
define <2 x double> @test_positive_zero_vector(<2 x double> %X) {
; CHECK-LABEL: @test_positive_zero_vector(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan <2 x double> @llvm.copysign.v2f64(<2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>, <2 x double> [[X:%.*]])
; CHECK-NEXT: ret <2 x double> [[TMP1]]
;
%1 = fdiv nnan <2 x double> %X, <double 0.0, double 0.0>
ret <2 x double> %1
}
define <2 x double> @test_negative_zero_vector(<2 x double> %X) {
; CHECK-LABEL: @test_negative_zero_vector(
; CHECK-NEXT: [[TMP1:%.*]] = fdiv nnan <2 x double> [[X:%.*]], <double -0.000000e+00, double 0.000000e+00>
; CHECK-NEXT: ret <2 x double> [[TMP1]]
;
%1 = fdiv nnan <2 x double> %X, <double -0.0, double 0.0>
ret <2 x double> %1
}