llvm-project/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll
Nikita Popov d9a5aa8e2d
[PatternMatch] Do not accept undef elements in m_AllOnes() and friends (#88217)
Change all the cstval_pred_ty based PatternMatch helpers (things like
m_AllOnes and m_Zero) to only allow poison elements inside vector
splats, not undef elements.

Historically, we used to represent non-demanded elements in vectors
using undef. Nowadays, we use poison instead. As such, I believe that
support for undef in vector splats is no longer useful.

At the same time, while poison splat elements are pretty much always
safe to ignore, this is not generally the case for undef elements. We
have existing miscompiles in our tests due to this (see the
masked-merge-*.ll tests changed here) and it's easy to miss such cases
in the future, now that we write tests using poison instead of undef
elements.

I think overall, keeping support for undef elements no longer makes
sense, and we should drop it. Once this is done consistently, I think we
may also consider allowing poison in m_APInt by default, as doing that
change is much less risky than doing the same with undef.

This change involves a substantial amount of test changes. For most
tests, I've just replaced undef with poison, as I don't think there is
value in retaining both. For some tests (where the distinction between
undef and poison is important), I've duplicated tests.
2024-04-17 18:22:05 +09:00

1242 lines
42 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
; fneg (fneg X) ==> X
define float @fneg_fneg_var(float %a) {
; CHECK-LABEL: @fneg_fneg_var(
; CHECK-NEXT: ret float [[A:%.*]]
;
%r = fneg float %a
%r1 = fneg float %r
ret float %r1
}
; fneg (fsub -0.0, X) ==> X
define float @fsub_-0_x(float %a) {
; CHECK-LABEL: @fsub_-0_x(
; CHECK-NEXT: ret float [[A:%.*]]
;
%t1 = fsub float -0.0, %a
%ret = fneg float %t1
ret float %ret
}
define <2 x float> @fsub_-0_x_vec(<2 x float> %a) {
; CHECK-LABEL: @fsub_-0_x_vec(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
%ret = fneg <2 x float> %t1
ret <2 x float> %ret
}
define <2 x float> @fsub_-0_x_vec_poison_elts(<2 x float> %a) {
; CHECK-LABEL: @fsub_-0_x_vec_poison_elts(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> <float -0.0, float poison>, %a
%ret = fneg <2 x float> %t1
ret <2 x float> %ret
}
define <2 x float> @fsub_negzero_vec_poison_elts(<2 x float> %x) {
; CHECK-LABEL: @fsub_negzero_vec_poison_elts(
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
;
%r = fsub nsz <2 x float> %x, <float poison, float -0.0>
ret <2 x float> %r
}
; fsub -0.0, (fsub -0.0, X) ==> X
define float @fsub_-0_-0_x(float %a) {
; CHECK-LABEL: @fsub_-0_-0_x(
; CHECK-NEXT: ret float [[A:%.*]]
;
%t1 = fsub float -0.0, %a
%ret = fsub float -0.0, %t1
ret float %ret
}
; fsub -0.0, (fneg X) ==> X
define float @fneg_x(float %a) {
; CHECK-LABEL: @fneg_x(
; CHECK-NEXT: ret float [[A:%.*]]
;
%t1 = fneg float %a
%ret = fsub float -0.0, %t1
ret float %ret
}
define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) {
; CHECK-LABEL: @fsub_-0_-0_x_vec(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
%ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
ret <2 x float> %ret
}
define <2 x float> @fneg_x_vec(<2 x float> %a) {
; CHECK-LABEL: @fneg_x_vec(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fneg <2 x float> %a
%ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
ret <2 x float> %ret
}
define <2 x float> @fsub_-0_-0_x_vec_poison_elts(<2 x float> %a) {
; CHECK-LABEL: @fsub_-0_-0_x_vec_poison_elts(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> <float poison, float -0.0>, %a
%ret = fsub <2 x float> <float -0.0, float poison>, %t1
ret <2 x float> %ret
}
define <2 x float> @fneg_x_vec_poison_elts(<2 x float> %a) {
; CHECK-LABEL: @fneg_x_vec_poison_elts(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fneg <2 x float> %a
%ret = fsub <2 x float> <float -0.0, float poison>, %t1
ret <2 x float> %ret
}
; fsub -0.0, (fsub 0.0, X) != X
define float @fsub_-0_0_x(float %a) {
; CHECK-LABEL: @fsub_-0_0_x(
; CHECK-NEXT: [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[RET:%.*]] = fsub float -0.000000e+00, [[T1]]
; CHECK-NEXT: ret float [[RET]]
;
%t1 = fsub float 0.0, %a
%ret = fsub float -0.0, %t1
ret float %ret
}
; fsub 0.0, (fsub -0.0, X) != X
define float @fsub_0_-0_x(float %a) {
; CHECK-LABEL: @fsub_0_-0_x(
; CHECK-NEXT: [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[RET:%.*]] = fsub float 0.000000e+00, [[T1]]
; CHECK-NEXT: ret float [[RET]]
;
%t1 = fsub float -0.0, %a
%ret = fsub float 0.0, %t1
ret float %ret
}
; fsub X, 0 ==> X
define float @fsub_x_0(float %x) {
; CHECK-LABEL: @fsub_x_0(
; CHECK-NEXT: ret float [[X:%.*]]
;
%r = fsub float %x, 0.0
ret float %r
}
define <2 x float> @fsub_x_0_vec_poison(<2 x float> %x) {
; CHECK-LABEL: @fsub_x_0_vec_poison(
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
;
%r = fsub <2 x float> %x, <float poison, float 0.0>
ret <2 x float> %r
}
; fadd X, -0 ==> X
define float @fadd_x_n0(float %a) {
; CHECK-LABEL: @fadd_x_n0(
; CHECK-NEXT: ret float [[A:%.*]]
;
%ret = fadd float %a, -0.0
ret float %ret
}
define <2 x float> @fadd_x_n0_vec_poison_elt(<2 x float> %a) {
; CHECK-LABEL: @fadd_x_n0_vec_poison_elt(
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%ret = fadd <2 x float> %a, <float -0.0, float poison>
ret <2 x float> %ret
}
; fmul X, 1.0 ==> X
define double @fmul_X_1(double %a) {
; CHECK-LABEL: @fmul_X_1(
; CHECK-NEXT: ret double [[A:%.*]]
;
%b = fmul double 1.0, %a
ret double %b
}
define half @fmul_nnan_ninf_nneg_0.0(i15 %x) {
; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0(
; CHECK-NEXT: ret half 0xH0000
;
%f = uitofp i15 %x to half
%r = fmul half %f, 0.0
ret half %r
}
define half @fmul_nnan_ninf_nneg_n0.0(i15 %x) {
; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0(
; CHECK-NEXT: ret half 0xH8000
;
%f = uitofp i15 %x to half
%r = fmul half %f, -0.0
ret half %r
}
; negative test - the int could be big enough to round to INF
define half @fmul_nnan_nneg_0.0(i16 %x) {
; CHECK-LABEL: @fmul_nnan_nneg_0.0(
; CHECK-NEXT: [[F:%.*]] = uitofp i16 [[X:%.*]] to half
; CHECK-NEXT: [[R:%.*]] = fmul half [[F]], 0xH0000
; CHECK-NEXT: ret half [[R]]
;
%f = uitofp i16 %x to half
%r = fmul half %f, 0.0
ret half %r
}
define double @fmul_nnan_ninf_nneg_n0.0_commute(i127 %x) {
; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0_commute(
; CHECK-NEXT: ret double -0.000000e+00
;
%f = uitofp i127 %x to float
%e = fpext float %f to double
%r = fmul double -0.0, %e
ret double %r
}
define float @src_mul_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f) {
; CHECK-LABEL: @src_mul_nzero_neg(
; CHECK-NEXT: ret float 0.000000e+00
;
%r = fmul float %f, -0.0
ret float %r
}
define <2 x float> @src_mul_zero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) {
; CHECK-LABEL: @src_mul_zero_neg(
; CHECK-NEXT: ret <2 x float> <float -0.000000e+00, float -0.000000e+00>
;
%r = fmul <2 x float> <float 0.0, float 0.0>, %f
ret <2 x float> %r
}
define <2 x float> @src_mul_zero_and_nzero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) {
; CHECK-LABEL: @src_mul_zero_and_nzero_neg(
; CHECK-NEXT: ret <2 x float> <float 0.000000e+00, float -0.000000e+00>
;
%r = fmul <2 x float> <float -0.0, float 0.0>, %f
ret <2 x float> %r
}
define float @src_muladd_zero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) {
; CHECK-LABEL: @src_muladd_zero_neg(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.fmuladd.f32(float [[F:%.*]], float 0.000000e+00, float [[ADD:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%r = call float @llvm.fmuladd.f32(float %f, float 0.0, float %add)
ret float %r
}
define float @src_fma_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) {
; CHECK-LABEL: @src_fma_nzero_neg(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.fma.f32(float -0.000000e+00, float [[F:%.*]], float [[ADD:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%r = call float @llvm.fma.f32(float -0.0, float %f, float %add)
ret float %r
}
; Make sure we can infer %x can't be 0 based on assumes.
define { float, float } @test_fmul_0_assumed_finite(float %x) {
; CHECK-LABEL: @test_fmul_0_assumed_finite(
; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[IS_FINITE_X:%.*]] = fcmp one float [[FABS_X]], 0x7FF0000000000000
; CHECK-NEXT: call void @llvm.assume(i1 [[IS_FINITE_X]])
; CHECK-NEXT: ret { float, float } { float 0.000000e+00, float -0.000000e+00 }
;
%fabs.x = call float @llvm.fabs.f32(float %x)
%is.finite.x = fcmp one float %fabs.x, 0x7FF0000000000000
call void @llvm.assume(i1 %is.finite.x)
%mul.0 = fmul float %fabs.x, 0.0
%mul.neg0 = fmul float %fabs.x, -0.0
%ins.0 = insertvalue { float, float } poison, float %mul.0, 0
%ins.1 = insertvalue { float, float } %ins.0, float %mul.neg0, 1
ret { float, float } %ins.1
}
; negative test - the int could be big enough to round to INF
define double @fmul_nnan_ninf_nneg_0.0_commute(i128 %x) {
; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0_commute(
; CHECK-NEXT: [[F:%.*]] = uitofp i128 [[X:%.*]] to float
; CHECK-NEXT: [[E:%.*]] = fpext float [[F]] to double
; CHECK-NEXT: [[R:%.*]] = fmul double 0.000000e+00, [[E]]
; CHECK-NEXT: ret double [[R]]
;
%f = uitofp i128 %x to float
%e = fpext float %f to double
%r = fmul double 0.0, %e
ret double %r
}
; PR2642
define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
; CHECK-LABEL: @fmul_X_1_vec(
; CHECK-NEXT: ret <4 x float> [[X:%.*]]
;
%m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
ret <4 x float> %m
}
; fdiv X, 1.0 ==> X
define float @fdiv_x_1(float %a) {
; CHECK-LABEL: @fdiv_x_1(
; CHECK-NEXT: ret float [[A:%.*]]
;
%ret = fdiv float %a, 1.0
ret float %ret
}
; We can't optimize away the fadd in this test because the input
; value to the function and subsequently to the fadd may be -0.0.
; In that one special case, the result of the fadd should be +0.0
; rather than the first parameter of the fadd.
; Fragile test warning: We need 6 sqrt calls to trigger the bug
; because the internal logic has a magic recursion limit of 6.
; This is presented without any explanation or ability to customize.
declare float @sqrtf(float)
define float @PR22688(float %x) {
; CHECK-LABEL: @PR22688(
; CHECK-NEXT: [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]])
; CHECK-NEXT: [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]])
; CHECK-NEXT: [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]])
; CHECK-NEXT: [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]])
; CHECK-NEXT: [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]])
; CHECK-NEXT: [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00
; CHECK-NEXT: ret float [[TMP7]]
;
%1 = call float @sqrtf(float %x)
%2 = call float @sqrtf(float %1)
%3 = call float @sqrtf(float %2)
%4 = call float @sqrtf(float %3)
%5 = call float @sqrtf(float %4)
%6 = call float @sqrtf(float %5)
%7 = fadd float %6, 0.0
ret float %7
}
declare float @llvm.fabs.f32(float)
declare double @llvm.fabs.f64(double)
declare float @llvm.canonicalize.f32(float)
declare float @llvm.floor.f32(float)
declare float @llvm.ceil.f32(float)
declare float @llvm.trunc.f32(float)
declare float @llvm.rint.f32(float)
declare float @llvm.nearbyint.f32(float)
declare float @llvm.round.f32(float)
declare float @llvm.roundeven.f32(float)
declare float @llvm.fptrunc.round.f32.f64(double, metadata)
declare float @llvm.arithmetic.fence.f32(float)
declare float @llvm.copysign.f32(float, float)
declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
declare float @llvm.sqrt.f32(float)
declare float @llvm.maxnum.f32(float, float)
declare void @llvm.assume(i1 noundef)
define float @fabs_select_positive_constants(i32 %c) {
; CHECK-LABEL: @fabs_select_positive_constants(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
; CHECK-NEXT: ret float [[SELECT]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 1.0, float 2.0
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_positive_constants_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
; CHECK-NEXT: ret <2 x float> [[SELECT]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_constant_variable(i32 %c, float %x) {
; CHECK-LABEL: @fabs_select_constant_variable(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 1.0, float %x
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
; CHECK-LABEL: @fabs_select_constant_variable_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]]
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_neg0_pos0(i32 %c) {
; CHECK-LABEL: @fabs_select_neg0_pos0(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float -0.0, float 0.0
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_neg0_neg1(i32 %c) {
; CHECK-LABEL: @fabs_select_neg0_neg1(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float -0.0, float -1.0
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00>
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_nan_nan(i32 %c) {
; CHECK-LABEL: @fabs_select_nan_nan(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
; CHECK-NEXT: ret float [[SELECT]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_nan_nan_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
; CHECK-NEXT: ret <2 x float> [[SELECT]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_negnan_nan(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_nan(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_nan_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_negnan_negnan(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_negnan(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_negnan_negzero(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_negzero(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00>
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
define float @fabs_select_negnan_zero(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_zero(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
; CHECK-NEXT: ret float [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
%fabs = call float @llvm.fabs.f32(float %select)
ret float %fabs
}
define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
; CHECK-LABEL: @fabs_select_negnan_zero_vector(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
ret <2 x float> %fabs
}
; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
; an arbitrary sign bit.
define float @fabs_sqrt(float %a) {
; CHECK-LABEL: @fabs_sqrt(
; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
; CHECK-NEXT: ret float [[FABS]]
;
%sqrt = call float @llvm.sqrt.f32(float %a)
%fabs = call float @llvm.fabs.f32(float %sqrt)
ret float %fabs
}
; The fabs can't be eliminated because the nnan sqrt may still return -0.
define float @fabs_sqrt_nnan(float %a) {
; CHECK-LABEL: @fabs_sqrt_nnan(
; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
; CHECK-NEXT: ret float [[FABS]]
;
%sqrt = call nnan float @llvm.sqrt.f32(float %a)
%fabs = call float @llvm.fabs.f32(float %sqrt)
ret float %fabs
}
; The fabs can't be eliminated because the nsz sqrt may still return NaN.
define float @fabs_sqrt_nsz(float %a) {
; CHECK-LABEL: @fabs_sqrt_nsz(
; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
; CHECK-NEXT: ret float [[FABS]]
;
%sqrt = call nsz float @llvm.sqrt.f32(float %a)
%fabs = call float @llvm.fabs.f32(float %sqrt)
ret float %fabs
}
; The fabs can be eliminated because we're nsz and nnan.
define float @fabs_sqrt_nnan_nsz(float %a) {
; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: ret float [[SQRT]]
;
%sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
%fabs = call float @llvm.fabs.f32(float %sqrt)
ret float %fabs
}
; The second fabs can be eliminated because the operand to sqrt cannot be -0.
define float @fabs_sqrt_nnan_fabs(float %a) {
; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
; CHECK-NEXT: ret float [[SQRT]]
;
%b = call float @llvm.fabs.f32(float %a)
%sqrt = call nnan float @llvm.sqrt.f32(float %b)
%fabs = call float @llvm.fabs.f32(float %sqrt)
ret float %fabs
}
define float @fabs_select_positive_constants_vector_extract(i32 %c) {
; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
; CHECK-NEXT: ret float [[EXTRACT]]
;
%cmp = icmp eq i32 %c, 0
%select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
%extract = extractelement <2 x float> %select, i32 0
%fabs = call float @llvm.fabs.f32(float %extract)
ret float %fabs
}
; Y - (Y - X) --> X
define float @fsub_fsub_common_op(float %x, float %y) {
; CHECK-LABEL: @fsub_fsub_common_op(
; CHECK-NEXT: ret float [[X:%.*]]
;
%s = fsub float %y, %x
%r = fsub reassoc nsz float %y, %s
ret float %r
}
define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fsub_fsub_common_op_vec(
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
;
%s = fsub <2 x float> %y, %x
%r = fsub reassoc nsz <2 x float> %y, %s
ret <2 x float> %r
}
; Negative test - fsub is not commutative.
; Y - (X - Y) --> (Y - X) + Y (canonicalized)
define float @fsub_fsub_wrong_common_op(float %x, float %y) {
; CHECK-LABEL: @fsub_fsub_wrong_common_op(
; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
; CHECK-NEXT: ret float [[R]]
;
%s = fsub float %x, %y
%r = fsub reassoc nsz float %y, %s
ret float %r
}
; Negative test - negated operand needed.
; (Y - X) - Y --> -X
define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
; CHECK-NEXT: ret float [[R]]
;
%s = fsub float %y, %x
%r = fsub reassoc nsz float %s, %y
ret float %r
}
; Negative test - fsub is not commutative.
; (X - Y) - Y --> ?
define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
; CHECK-NEXT: ret float [[R]]
;
%s = fsub float %x, %y
%r = fsub reassoc nsz float %s, %y
ret float %r
}
; (Y + X) - Y --> X
define float @fadd_fsub_common_op(float %x, float %y) {
; CHECK-LABEL: @fadd_fsub_common_op(
; CHECK-NEXT: ret float [[X:%.*]]
;
%a = fadd float %y, %x
%r = fsub reassoc nsz float %a, %y
ret float %r
}
; (X + Y) - Y --> X
define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
;
%a = fadd <2 x float> %x, %y
%r = fsub reassoc nsz <2 x float> %a, %y
ret <2 x float> %r
}
; Negative test - negated operand needed.
; Y - (Y + X) --> -X
define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
; CHECK-NEXT: [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
; CHECK-NEXT: ret float [[R]]
;
%a = fadd float %y, %x
%r = fsub reassoc nsz float %y, %a
ret float %r
}
; Negative test - negated operand needed.
; Y - (X + Y) --> -X
define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
; CHECK-NEXT: ret float [[R]]
;
%a = fadd float %x, %y
%r = fsub reassoc nsz float %y, %a
ret float %r
}
; Y + (X - Y) --> X
define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fsub_fadd_common_op_vec(
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
;
%s = fsub <2 x float> %x, %y
%r = fadd reassoc nsz <2 x float> %y, %s
ret <2 x float> %r
}
; (X - Y) + Y --> X
define float @fsub_fadd_common_op_commute(float %x, float %y) {
; CHECK-LABEL: @fsub_fadd_common_op_commute(
; CHECK-NEXT: ret float [[X:%.*]]
;
%s = fsub float %x, %y
%r = fadd reassoc nsz float %s, %y
ret float %r
}
; Negative test.
; Y + (Y - X) --> ?
define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
; CHECK-NEXT: ret float [[R]]
;
%s = fsub float %y, %x
%r = fadd reassoc nsz float %y, %s
ret float %r
}
; Negative test.
; (Y - X) + Y --> ?
define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
; CHECK-NEXT: ret float [[R]]
;
%s = fsub float %y, %x
%r = fadd reassoc nsz float %s, %y
ret float %r
}
; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
define float @maxnum_with_poszero_op(float %a) {
; CHECK-LABEL: @maxnum_with_poszero_op(
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00)
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
; CHECK-NEXT: ret float [[FABS]]
;
%max = call float @llvm.maxnum.f32(float %a, float 0.0)
%fabs = call float @llvm.fabs.f32(float %max)
ret float %fabs
}
define float @maxnum_with_poszero_op_commute(float %a) {
; CHECK-LABEL: @maxnum_with_poszero_op_commute(
; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]])
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
; CHECK-NEXT: ret float [[FABS]]
;
%sqrt = call float @llvm.sqrt.f32(float %a)
%max = call float @llvm.maxnum.f32(float 0.0, float %sqrt)
%fabs = call float @llvm.fabs.f32(float %max)
ret float %fabs
}
define float @maxnum_with_negzero_op(float %a) {
; CHECK-LABEL: @maxnum_with_negzero_op(
; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]])
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
; CHECK-NEXT: ret float [[FABS]]
;
%nnan = call nnan float @llvm.sqrt.f32(float %a)
%fabsa = call float @llvm.fabs.f32(float %nnan)
%max = call float @llvm.maxnum.f32(float -0.0, float %fabsa)
%fabs = call float @llvm.fabs.f32(float %max)
ret float %fabs
}
define float @maxnum_with_negzero_op_commute(float %a) {
; CHECK-LABEL: @maxnum_with_negzero_op_commute(
; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00)
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
; CHECK-NEXT: ret float [[FABS]]
;
%nnan = call nnan float @llvm.sqrt.f32(float %a)
%fabsa = call float @llvm.fabs.f32(float %nnan)
%max = call float @llvm.maxnum.f32(float %fabsa, float -0.0)
%fabs = call float @llvm.fabs.f32(float %max)
ret float %fabs
}
; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
define float @maxnum_with_pos_one_op(float %a) {
; CHECK-LABEL: @maxnum_with_pos_one_op(
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00)
; CHECK-NEXT: ret float [[MAX]]
;
%max = call float @llvm.maxnum.f32(float %a, float 1.0)
%fabs = call float @llvm.fabs.f32(float %max)
ret float %fabs
}
define double @fadd_nnan_inf_op0(double %x) {
; CHECK-LABEL: @fadd_nnan_inf_op0(
; CHECK-NEXT: ret double 0x7FF0000000000000
;
%r = fadd nnan double 0x7ff0000000000000, %x
ret double %r
}
define double @fadd_nnan_inf_op1(double %x) {
; CHECK-LABEL: @fadd_nnan_inf_op1(
; CHECK-NEXT: ret double 0x7FF0000000000000
;
%r = fadd nnan double %x, 0x7ff0000000000000
ret double %r
}
define <2 x double> @fadd_nnan_neginf_op1(<2 x double> %x) {
; CHECK-LABEL: @fadd_nnan_neginf_op1(
; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double poison>
;
%r = fadd nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
ret <2 x double> %r
}
define double @fadd_nnan_neginf_op0(double %x) {
; CHECK-LABEL: @fadd_nnan_neginf_op0(
; CHECK-NEXT: ret double 0xFFF0000000000000
;
%r = fadd nnan double 0xfff0000000000000, %x
ret double %r
}
; negative test - requires nnan
define double @fadd_inf_op0(double %x) {
; CHECK-LABEL: @fadd_inf_op0(
; CHECK-NEXT: [[R:%.*]] = fadd double 0x7FF0000000000000, [[X:%.*]]
; CHECK-NEXT: ret double [[R]]
;
%r = fadd double 0x7ff0000000000000, %x
ret double %r
}
define double @fsub_nnan_inf_op0(double %x) {
; CHECK-LABEL: @fsub_nnan_inf_op0(
; CHECK-NEXT: ret double 0x7FF0000000000000
;
%r = fsub nnan double 0x7ff0000000000000, %x
ret double %r
}
; flip sign
define double @fsub_nnan_inf_op1(double %x) {
; CHECK-LABEL: @fsub_nnan_inf_op1(
; CHECK-NEXT: ret double 0xFFF0000000000000
;
%r = fsub nnan double %x, 0x7ff0000000000000
ret double %r
}
define <2 x double> @fsub_nnan_inf_op1_vec(<2 x double> %x) {
; CHECK-LABEL: @fsub_nnan_inf_op1_vec(
; CHECK-NEXT: ret <2 x double> <double 0x7FF0000000000000, double poison>
;
%r = fsub nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
ret <2 x double> %r
}
define <2 x double> @fsub_nnan_neginf_op0(<2 x double> %x) {
; CHECK-LABEL: @fsub_nnan_neginf_op0(
; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double poison>
;
%r = fsub nnan <2 x double> <double 0xfff0000000000000, double poison>, %x
ret <2 x double> %r
}
; flip sign
define double @fsub_nnan_neginf_op1(double %x) {
; CHECK-LABEL: @fsub_nnan_neginf_op1(
; CHECK-NEXT: ret double 0x7FF0000000000000
;
%r = fsub nnan double %x, 0xfff0000000000000
ret double %r
}
; negative test - requires nnan
define double @fsub_inf_op0(double %x) {
; CHECK-LABEL: @fsub_inf_op0(
; CHECK-NEXT: [[R:%.*]] = fsub double 0x7FF0000000000000, [[X:%.*]]
; CHECK-NEXT: ret double [[R]]
;
%r = fsub double 0x7ff0000000000000, %x
ret double %r
}
define i1 @canonicalize_known_positive(float %a) {
; CHECK-LABEL: @canonicalize_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.canonicalize.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @canonicalize_unknown_positive(float %unknown) {
; CHECK-LABEL: @canonicalize_unknown_positive(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[UNKNOWN:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%cmp = fcmp nnan oge float %unknown, 0.0
ret i1 %cmp
}
define i1 @arithmetic_fence_known_positive(float %a) {
; CHECK-LABEL: @arithmetic_fence_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.arithmetic.fence.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @arithmetic_fence_unknown_positive(float %unknown) {
; CHECK-LABEL: @arithmetic_fence_unknown_positive(
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[KNOWN_POSITIVE]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%known.positive = call float @llvm.arithmetic.fence.f32(float %unknown)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @copysign_known_positive_maybe_neg0(float %unknown, float %sign) {
; CHECK-LABEL: @copysign_known_positive_maybe_neg0(
; CHECK-NEXT: [[SQRT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SIGN:%.*]])
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[SQRT]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call ninf nnan float @llvm.sqrt.f32(float %sign)
%copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt)
%cmp = fcmp nnan oge float %copysign, 0.0
ret i1 %cmp
}
define i1 @copysign_known_positive(float %unknown, float %sign) {
; CHECK-LABEL: @copysign_known_positive(
; CHECK-NEXT: ret i1 true
;
%sqrt = call ninf nnan nsz float @llvm.sqrt.f32(float %sign)
%copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt)
%cmp = fcmp nnan oge float %copysign, 0.0
ret i1 %cmp
}
define i1 @copysign_unknown_positive(float %unknown, float %unknown.sign) {
; CHECK-LABEL: @copysign_unknown_positive(
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[UNKNOWN_SIGN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%copysign = call float @llvm.copysign.f32(float %unknown, float %unknown.sign)
%cmp = fcmp nnan oge float %copysign, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/Y-EyY3
define i1 @floor_known_positive(float %a) {
; CHECK-LABEL: @floor_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.floor.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @floor_unknown_positive(float %unknown) {
; CHECK-LABEL: @floor_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.floor.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/3tBUoW
define i1 @ceil_known_positive(float %a) {
; CHECK-LABEL: @ceil_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.ceil.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @ceil_unknown_positive(float %unknown) {
; CHECK-LABEL: @ceil_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.ceil.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.ceil.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/RbyJPX
define i1 @trunc_known_positive(float %a) {
; CHECK-LABEL: @trunc_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.trunc.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @trunc_unknown_positive(float %unknown) {
; CHECK-LABEL: @trunc_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.trunc.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.trunc.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/bjC2Jm
define i1 @rint_known_positive(float %a) {
; CHECK-LABEL: @rint_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.rint.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @rint_unknown_positive(float %unknown) {
; CHECK-LABEL: @rint_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.rint.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.rint.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/dFiL9n
define i1 @nearbyint_known_positive(float %a) {
; CHECK-LABEL: @nearbyint_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.nearbyint.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @nearbyint_unknown_positive(float %unknown) {
; CHECK-LABEL: @nearbyint_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.nearbyint.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.nearbyint.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/kPhS-d
define i1 @round_known_positive(float %a) {
; CHECK-LABEL: @round_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.round.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @round_unknown_positive(float %unknown) {
; CHECK-LABEL: @round_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.round.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.round.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
; https://alive2.llvm.org/ce/z/Z_tfsu
define i1 @roundeven_known_positive(float %a) {
; CHECK-LABEL: @roundeven_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call float @llvm.fabs.f32(float %a)
%known.positive = call float @llvm.roundeven.f32(float %fabs)
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @roundeven_unknown_positive(float %unknown) {
; CHECK-LABEL: @roundeven_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.roundeven.f32(float [[UNKNOWN:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.roundeven.f32(float %unknown)
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}
define i1 @fptrunc_round_known_positive(double %a) {
; CHECK-LABEL: @fptrunc_round_known_positive(
; CHECK-NEXT: ret i1 true
;
%fabs = call double @llvm.fabs.f64(double %a)
%known.positive = call float @llvm.fptrunc.round.f32.f64(double %fabs, metadata !"round.downward")
%cmp = fcmp nnan oge float %known.positive, 0.0
ret i1 %cmp
}
define i1 @fptrunc_round_unknown_positive(double %unknown) {
; CHECK-LABEL: @fptrunc_round_unknown_positive(
; CHECK-NEXT: [[OP:%.*]] = call float @llvm.fptrunc.round.f32.f64(double [[UNKNOWN:%.*]], metadata !"round.downward")
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%op = call float @llvm.fptrunc.round.f32.f64(double %unknown, metadata !"round.downward")
%cmp = fcmp nnan oge float %op, 0.0
ret i1 %cmp
}