CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
2708 lines
143 KiB
LLVM
2708 lines
143 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
|
|
|
|
declare float @llvm.fabs.f32(float)
|
|
declare float @llvm.copysign.f32(float, float)
|
|
declare void @llvm.assume(i1 noundef)
|
|
declare float @llvm.log2.f32(float)
|
|
declare float @llvm.exp2.f32(float)
|
|
declare float @llvm.trunc.f32(float)
|
|
declare float @llvm.arithmetic.fence.f32(float)
|
|
declare float @llvm.minnum.f32(float, float)
|
|
declare float @llvm.maxnum.f32(float, float)
|
|
|
|
declare nofpclass(inf norm sub zero) float @nan_only()
|
|
|
|
define float @ninf_user_select_inf(i1 %cond, float %x, float %y) {
|
|
; CHECK-LABEL: define float @ninf_user_select_inf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float +inf
|
|
; CHECK-NEXT: [[NINF_USER:%.*]] = fmul ninf float [[Y]], [[SELECT]]
|
|
; CHECK-NEXT: ret float [[NINF_USER]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%ninf.user = fmul ninf float %y, %select
|
|
ret float %ninf.user
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf_poison() {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_poison() {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
ret float poison
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf_undef() {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_undef() {
|
|
; CHECK-NEXT: ret float undef
|
|
;
|
|
ret float undef
|
|
}
|
|
|
|
define nofpclass(all) float @ret_nofpclass_all_undef() {
|
|
; CHECK-LABEL: define nofpclass(all) float @ret_nofpclass_all_undef() {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
ret float undef
|
|
}
|
|
|
|
; Use + callsite implies no values, should fold undef to poison.
|
|
define nofpclass(nan) float @undef_folds_to_poison_arg() {
|
|
; CHECK-LABEL: define nofpclass(nan) float @undef_folds_to_poison_arg() {
|
|
; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float nofpclass(inf zero sub norm) undef)
|
|
; CHECK-NEXT: ret float [[FENCE]]
|
|
;
|
|
%fence = call float @llvm.arithmetic.fence.f32(float nofpclass(inf sub norm zero) undef)
|
|
ret float %fence
|
|
}
|
|
|
|
; Make sure there's no infinite loop
|
|
define nofpclass(all) float @ret_nofpclass_all_var(float %arg) {
|
|
; CHECK-LABEL: define nofpclass(all) float @ret_nofpclass_all_var
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
ret float %arg
|
|
}
|
|
|
|
; Make sure there's no infinite loop
|
|
define nofpclass(all) <2 x float> @ret_nofpclass_all_var_vector(<2 x float> %arg) {
|
|
; CHECK-LABEL: define nofpclass(all) <2 x float> @ret_nofpclass_all_var_vector
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: ret <2 x float> poison
|
|
;
|
|
ret <2 x float> %arg
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__0() {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__0() {
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
ret float 0.0
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__pinf() {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__pinf() {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
ret float 0x7FF0000000000000
|
|
}
|
|
|
|
define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() {
|
|
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
ret float 0x7FF0000000000000
|
|
}
|
|
|
|
define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() {
|
|
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() {
|
|
; CHECK-NEXT: ret float -inf
|
|
;
|
|
ret float 0xFFF0000000000000
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__ninf() {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__ninf() {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
ret float 0xFFF0000000000000
|
|
}
|
|
|
|
|
|
; Negative test, do nothing
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_inf_lhs(i1 %cond, float nofpclass(inf) %x, float %y) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_inf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float nofpclass(inf) [[X:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[Y]]
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%select = select i1 %cond, float %x, float %y
|
|
ret float %select
|
|
}
|
|
|
|
; Make sure nofpclass from source argument is used, fold to %y
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_lhs(i1 %cond, float nofpclass(nan norm zero sub) %x, float %y) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float nofpclass(nan zero sub norm) [[X:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: ret float [[Y]]
|
|
;
|
|
%select = select i1 %cond, float %x, float %y
|
|
ret float %select
|
|
}
|
|
|
|
; Make sure nofpclass from source argument is used, fold to %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_rhs(i1 %cond, float %x, float nofpclass(nan norm zero sub) %y) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(nan zero sub norm) [[Y:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%select = select i1 %cond, float %x, float %y
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to ret %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_lhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%select = select i1 %cond, float 0x7FF0000000000000, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to ret %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to poison
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_or_ninf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_or_ninf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%select = select i1 %cond, float 0x7FF0000000000000, float 0xFFF0000000000000
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to poison
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_ninf_or_pinf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_ninf_or_pinf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to pos inf
|
|
define nofpclass(ninf) float @ret_nofpclass_ninf__select_ninf_or_pinf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__select_ninf_or_pinf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float +inf
|
|
;
|
|
%select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to neg inf
|
|
define nofpclass(pinf) float @ret_nofpclass_pinf__select_ninf_or_pinf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__select_ninf_or_pinf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float -inf
|
|
;
|
|
%select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to poison
|
|
define nofpclass(zero) float @ret_nofpclass_zero__select_pzero_or_nzero(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero__select_pzero_or_nzero
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%select = select i1 %cond, float 0.0, float -0.0
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to +0
|
|
define nofpclass(nzero) float @ret_nofpclass_nzero__select_pzero_or_nzero(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nzero) float @ret_nofpclass_nzero__select_pzero_or_nzero
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%select = select i1 %cond, float 0.0, float -0.0
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to -0
|
|
define nofpclass(pzero) float @ret_nofpclass_pzero__select_pzero_or_nzero(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(pzero) float @ret_nofpclass_pzero__select_pzero_or_nzero
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float -0.000000e+00
|
|
;
|
|
%select = select i1 %cond, float 0.0, float -0.0
|
|
ret float %select
|
|
}
|
|
|
|
; Fold to ret %x
|
|
define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector(<2 x i1> %cond, <2 x float> %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector
|
|
; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) {
|
|
; CHECK-NEXT: ret <2 x float> [[X]]
|
|
;
|
|
%select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> %x
|
|
ret <2 x float> %select
|
|
}
|
|
|
|
; Fold to ret %x
|
|
define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector_undef(<2 x i1> %cond, <2 x float> %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector_undef
|
|
; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) {
|
|
; CHECK-NEXT: ret <2 x float> [[X]]
|
|
;
|
|
%select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float poison>, <2 x float> %x
|
|
ret <2 x float> %select
|
|
}
|
|
|
|
; Fold to ret %x
|
|
define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_mixed_inf_lhs_vector(<2 x i1> %cond, <2 x float> %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_mixed_inf_lhs_vector
|
|
; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) {
|
|
; CHECK-NEXT: ret <2 x float> [[X]]
|
|
;
|
|
%select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0xFFF0000000000000>, <2 x float> %x
|
|
ret <2 x float> %select
|
|
}
|
|
|
|
; Can't delete the select
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_multi_use_pinf_lhs(i1 %cond, float %x, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_multi_use_pinf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float +inf, float [[X]]
|
|
; CHECK-NEXT: store float [[SELECT]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%select = select i1 %cond, float 0x7FF0000000000000, float %x
|
|
store float %select, ptr %ptr
|
|
ret float %select
|
|
}
|
|
|
|
; Can't do anything
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_p0_lhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_p0_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0.000000e+00, float [[X]]
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%select = select i1 %cond, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Can't do anything
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_p0_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_p0_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0.000000e+00
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0.0
|
|
ret float %select
|
|
}
|
|
|
|
; Can't do anything
|
|
define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_lhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float +inf, float [[X]]
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%select = select i1 %cond, float 0x7FF0000000000000, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Can't do anything
|
|
define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float +inf
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
ret float %select
|
|
}
|
|
|
|
define nofpclass(inf nan) float @ret_nofpclass_inf_nan__select_chain_inf_nan_0(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan inf) float @ret_nofpclass_inf_nan__select_chain_inf_nan_0
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%select0 = select i1 %cond, float 0x7FF8000000000000, float %x
|
|
%select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
|
|
ret float %select1
|
|
}
|
|
|
|
define nofpclass(inf nan) float @ret_nofpclass_inf_nan__select_chain_inf_nan_1(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan inf) float @ret_nofpclass_inf_nan__select_chain_inf_nan_1
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%select0 = select i1 %cond, float %x, float 0x7FF8000000000000
|
|
%select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
|
|
ret float %select1
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nofpclass_nan__select_chain_inf_nan(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_chain_inf_nan
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[COND]], float +inf, float [[X]]
|
|
; CHECK-NEXT: ret float [[SELECT1]]
|
|
;
|
|
%select0 = select i1 %cond, float 0x7FF8000000000000, float %x
|
|
%select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
|
|
ret float %select1
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_0(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_0
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%select0 = select i1 %cond, float 0x7FF8000000000000, float %x
|
|
%select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
|
|
ret float %select1
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_1(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_1
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float +qnan
|
|
;
|
|
%select0 = select i1 %cond, float 0x7FF8000000000000, float %x
|
|
%select1 = select i1 %cond, float %select0, float 0x7FF0000000000000
|
|
ret float %select1
|
|
}
|
|
|
|
; Simplify to fabs %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_ninf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_ninf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0xFFF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
ret float %fabs
|
|
}
|
|
|
|
; Simplify to fabs %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float +inf
|
|
; CHECK-NEXT: ret float [[FABS]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
ret float %fabs
|
|
}
|
|
|
|
; Fold to fabs(%x), preserving a possible nan's payload bits
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float +inf
|
|
; CHECK-NEXT: ret float [[FABS]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
ret float %fabs
|
|
}
|
|
|
|
; Can fold to poison
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nan__fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
ret float %fabs
|
|
}
|
|
|
|
; Simplify to fneg %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__fneg_select_ninf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fneg_select_ninf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[X_NEG]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0xFFF0000000000000
|
|
%fneg = fneg float %select
|
|
ret float %fneg
|
|
}
|
|
|
|
; Simplify to fneg %x
|
|
define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_nonegatives_noinf___fneg_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_nonegatives_noinf___fneg_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[X_NEG]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fneg = fneg float %select
|
|
ret float %fneg
|
|
}
|
|
|
|
; Simplify to fneg %x
|
|
define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_nonegatives_noinf___fneg_select_ninf_lhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_nonegatives_noinf___fneg_select_ninf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[X_NEG]]
|
|
;
|
|
%select = select i1 %cond, float 0xFFF0000000000000, float %x
|
|
%fneg = fneg float %select
|
|
ret float %fneg
|
|
}
|
|
|
|
define nofpclass(pzero psub pnorm pinf) float @ret_nofpclass_nopositives___fneg_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives___fneg_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: [[FNEG:%.*]] = select i1 [[COND]], float [[X_NEG]], float -inf
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fneg = fneg float %select
|
|
ret float %fneg
|
|
}
|
|
|
|
; Fold to fneg fabs
|
|
define nofpclass(inf) float @ret_nofpclass_inf__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fneg_fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[DOTNEG]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
%fneg = fneg float %fabs
|
|
ret float %fneg
|
|
}
|
|
|
|
; Fold to fneg fabs, may need to preserve a nan payload
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives__fneg_fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[DOTNEG]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
%fneg = fneg float %fabs
|
|
ret float %fneg
|
|
}
|
|
|
|
|
|
; Fold to poison
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_nonan__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_nonan__fneg_fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs = call float @llvm.fabs.f32(float %select)
|
|
%fneg = fneg float %fabs
|
|
ret float %fneg
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_src_known_positive(float nofpclass(nan ninf nnorm nsub nzero) %always.positive) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_src_known_positive_or_nan(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
|
|
; CHECK-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_nnan_src_known_positive_or_nan(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_nnan_src_known_positive_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
|
|
;
|
|
%fabs = call nnan float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_src_known_positive_multiple_uses(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: store float [[ALWAYS_POSITIVE]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_src_known_positive_except_negzero_multiple_uses(float nofpclass(nan ninf nnorm nsub) %always.positive.or.nzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_except_negzero_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_NZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NZERO]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nzero)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_nsz_src_known_positive_except_negzero(float nofpclass(nan ninf nnorm nsub) %always.positive.or.nzero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_nsz_src_known_positive_except_negzero
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_NZERO:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NZERO]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %always.positive.or.nzero)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_nsz_src_known_positive_except_negzero_multiple_uses(float nofpclass(nan ninf nnorm nsub) %always.positive.or.nzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_nsz_src_known_positive_except_negzero_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_NZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: store float [[ALWAYS_POSITIVE_OR_NZERO]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NZERO]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %always.positive.or.nzero)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
; Take no-nan from flag
|
|
define nofpclass(nsub) float @ret_fabs_nnan_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nsub) float @ret_fabs_nnan_src_known_positive_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nnan float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
|
|
;
|
|
%fabs = call nnan float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
; Take no-infs from flag, which will then imply no neg
|
|
define nofpclass(nsub) float @ret_fabs_ninf_src_known_positive_or_ninf_or_nan_multiple_uses(float nofpclass(nan nnorm nsub nzero) %always.positive.or.ninf, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nsub) float @ret_fabs_ninf_src_known_positive_or_ninf_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NINF:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call ninf float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NINF]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NINF]]
|
|
;
|
|
%fabs = call ninf float @llvm.fabs.f32(float %always.positive.or.ninf)
|
|
store float %fabs, ptr %ptr
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fabs_src_known_negative(float nofpclass(nan pinf pnorm psub pzero) %always.negative) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_negative
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE]])
|
|
; CHECK-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative)
|
|
ret float %fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_src_known_negative_multiple_uses(float nofpclass(nan pinf pnorm psub pzero) %always.negative, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_src_known_negative_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_src_known_positive_multiple_uses(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_src_known_positive_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[ALWAYS_POSITIVE]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_src_known_negative_or_nan_multiple_uses(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_src_known_negative_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_NAN]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative.or.nan)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nonan_fneg_fabs_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fneg_fabs_src_known_positive_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nnan_fabs_src_known_negative_or_nan_multiple_uses(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nnan_fabs_src_known_negative_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_NAN]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nnan float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative.or.nan)
|
|
%fneg.fabs = fneg nnan float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nnan_src_known_negative_or_nan_multiple_uses(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nnan_src_known_negative_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nnan float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_NAN]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%fabs = call nnan float @llvm.fabs.f32(float %always.negative.or.nan)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nofpclass_nan_src__known_negative_or_nan_multiple_uses(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nofpclass_nan_src__known_negative_or_nan_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float nofpclass(nan) [[ALWAYS_NEGATIVE_OR_NAN]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float nofpclass(nan) %always.negative.or.nan)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
; Take no-posinf from ninf flag
|
|
define nofpclass(snan) float @ret_fneg_ninf_fabs_src_known_negative_or_posinf_multiple_uses(float nofpclass(nan pnorm psub pzero) %negative.or.neginf, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @ret_fneg_ninf_fabs_src_known_negative_or_posinf_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan pzero psub pnorm) [[NEGATIVE_OR_NEGINF:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[NEGATIVE_OR_NEGINF]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg ninf float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[NEGATIVE_OR_NEGINF]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %negative.or.neginf)
|
|
%fneg.fabs = fneg ninf float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
; Take no-posinf from ninf flag
|
|
define nofpclass(snan) float @ret_fneg_fabs_ninf_src_known_negative_or_posinf_multiple_uses(float nofpclass(nan pnorm psub pzero) %negative.or.neginf, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @ret_fneg_fabs_ninf_src_known_negative_or_posinf_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan pzero psub pnorm) [[NEGATIVE_OR_NEGINF:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call ninf float @llvm.fabs.f32(float [[NEGATIVE_OR_NEGINF]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[NEGATIVE_OR_NEGINF]]
|
|
;
|
|
%fabs = call ninf float @llvm.fabs.f32(float %negative.or.neginf)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_src_known_negative_or_poszero_multiple_uses(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_src_known_negative_or_poszero_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PZERO]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nsz_src_known_negative_or_poszero(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nsz_src_known_negative_or_poszero
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_PZERO]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nsz_src_known_negative_or_poszero_multiple_uses(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nsz_src_known_negative_or_poszero_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nsz float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PZERO]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nsz_src_known_negative_or_poszero_multiple_uses_fabs(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nsz_src_known_negative_or_poszero_multiple_uses_fabs
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nsz float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PZERO]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
store float %fabs, ptr %ptr
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs_src_known_negative_or_poszero_multiple_uses_fabs(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs_src_known_negative_or_poszero_multiple_uses_fabs
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PZERO]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nsz float [[FABS]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
store float %fabs, ptr %ptr
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs_src_known_negative_or_poszero(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs_src_known_negative_or_poszero
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_PZERO]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs_src_known_negative_or_poszero_multiple_uses(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs_src_known_negative_or_poszero_multiple_uses
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PZERO]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nsz float [[FABS]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative.or.pzero)
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_src_known_negative_multiple_uses_fabs(float nofpclass(nan pinf pnorm psub pzero) %always.negative, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_src_known_negative_multiple_uses_fabs
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.negative)
|
|
store float %fabs, ptr %ptr
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_src_known_positive_multiple_uses_fabs(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_src_known_positive_multiple_uses_fabs
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: store float [[ALWAYS_POSITIVE]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[ALWAYS_POSITIVE]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %always.positive)
|
|
store float %fabs, ptr %ptr
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nnan__known_positive__sign_known_negative_or_nan(float nofpclass(ninf nzero nsub nnorm) %known.positive) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nnan__known_positive__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[KNOWN_POSITIVE:%.*]]) {
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nnan float [[KNOWN_POSITIVE]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call nnan float @llvm.fabs.f32(float %known.positive)
|
|
%fneg.fabs = fneg nnan float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nnan__known_positive__sign_known_positive_or_negzero_or_nan(float nofpclass(ninf nsub nnorm) %known.positive.or.neg.zero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nnan__known_positive__sign_known_positive_or_negzero_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[KNOWN_POSITIVE_OR_NEG_ZERO]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nnan float [[FABS]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
%fneg.fabs = fneg nnan float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs__known_positive__sign_known_positive_or_negzero_or_nan(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs__known_positive__sign_known_positive_or_negzero_or_nan
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[KNOWN_POSITIVE_OR_NEG_ZERO]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs__known_positive__sign_known_positive_or_negzero_or_nan(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs__known_positive__sign_known_positive_or_negzero_or_nan
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]]) {
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nsz float [[KNOWN_POSITIVE_OR_NEG_ZERO]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs__known_positive__sign_known_positive_or_negzero_or_nan_multiple_use_fabs(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs__known_positive__sign_known_positive_or_negzero_or_nan_multiple_use_fabs
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[KNOWN_POSITIVE_OR_NEG_ZERO]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nsz float [[FABS]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
store float %fabs, ptr %ptr
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan_multiple_use_fabs(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan_multiple_use_fabs
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: store float [[KNOWN_POSITIVE_OR_NEG_ZERO]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nsz float [[KNOWN_POSITIVE_OR_NEG_ZERO]]
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
store float %fabs, ptr %ptr
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_nsz_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan_multiple_use_fneg(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_nsz_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan_multiple_use_fneg
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg nsz float [[KNOWN_POSITIVE_OR_NEG_ZERO]]
|
|
; CHECK-NEXT: store float [[FNEG_FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
%fneg.fabs = fneg nsz float %fabs
|
|
store float %fneg.fabs, ptr %ptr
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[KNOWN_POSITIVE_OR_NEG_ZERO]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
%copysign = fneg float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan__multi_use_fabs(float nofpclass(nan ninf nsub nnorm) %known.positive.or.neg.zero, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nsz__known_positive__sign_known_positive_or_negzero_or_nan__multi_use_fabs
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[KNOWN_POSITIVE_OR_NEG_ZERO:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: store float [[KNOWN_POSITIVE_OR_NEG_ZERO]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[KNOWN_POSITIVE_OR_NEG_ZERO]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call nsz float @llvm.fabs.f32(float %known.positive.or.neg.zero)
|
|
store float %fabs, ptr %ptr
|
|
%copysign = fneg float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @fneg_fabs_nnan__known_positive__sign_known_negative_or_nan_multi_use_fabs(float nofpclass(ninf nzero nsub nnorm) %known.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @fneg_fabs_nnan__known_positive__sign_known_negative_or_nan_multi_use_fabs
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[KNOWN_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nnan float @llvm.fabs.f32(float [[KNOWN_POSITIVE]])
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan float [[KNOWN_POSITIVE]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call nnan float @llvm.fabs.f32(float %known.positive)
|
|
store float %fabs, ptr %ptr
|
|
%copysign = fneg nnan float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
; Known fabs source is positive due to ninf flag
|
|
define nofpclass(nan) float @no_nan__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan(float nofpclass(nzero nsub nnorm) %known.positive.or.ninf) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @no_nan__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(nzero nsub nnorm) [[KNOWN_POSITIVE_OR_NINF:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg ninf float [[KNOWN_POSITIVE_OR_NINF]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.ninf)
|
|
%copysign = fneg ninf float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
; Known fabs source is positive due to ninf flag
|
|
define nofpclass(nan) float @no_nan__fneg_fabs_ninf__known_positive_or_ninf__sign_known_negative_or_nan(float nofpclass(nzero nsub nnorm) %known.positive.or.ninf) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @no_nan__fneg_fabs_ninf__known_positive_or_ninf__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(nzero nsub nnorm) [[KNOWN_POSITIVE_OR_NINF:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[KNOWN_POSITIVE_OR_NINF]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call ninf float @llvm.fabs.f32(float %known.positive.or.ninf)
|
|
%copysign = fneg float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can't tell fabs source is positive with no-pinf return
|
|
define nofpclass(nan pinf) float @no_nan_nopinf__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan(float nofpclass(nzero nsub nnorm) %known.positive.or.ninf) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf) float @no_nan_nopinf__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(nzero nsub nnorm) [[KNOWN_POSITIVE_OR_NINF:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[KNOWN_POSITIVE_OR_NINF]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.ninf)
|
|
%copysign = fneg float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can't tell fabs source is positive with ninf return
|
|
define nofpclass(nan ninf) float @no_nan_noninf__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan(float nofpclass(nzero nsub nnorm) %known.positive.or.ninf) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf) float @no_nan_noninf__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(nzero nsub nnorm) [[KNOWN_POSITIVE_OR_NINF:%.*]]) {
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[KNOWN_POSITIVE_OR_NINF]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.ninf)
|
|
%copysign = fneg float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can tell fabs source is positive with no inf return
|
|
define nofpclass(nan inf) float @no_nan_noinf__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan(float nofpclass(nzero nsub nnorm) %known.positive.or.ninf) {
|
|
; CHECK-LABEL: define nofpclass(nan inf) float @no_nan_noinf__fneg_ninf_fabs__known_positive_or_ninf__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(nzero nsub nnorm) [[KNOWN_POSITIVE_OR_NINF:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[KNOWN_POSITIVE_OR_NINF]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %known.positive.or.ninf)
|
|
%copysign = fneg float %fabs
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan) float @fneg_fabs_multiple_uses_fabs(i1 %cond, float %x, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @fneg_fabs_multiple_uses_fabs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[NAN:%.*]] = call float @nan_only()
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], float [[X]], float [[NAN]]
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SEL]])
|
|
; CHECK-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%nan = call float @nan_only()
|
|
%sel = select i1 %cond, float %x, float %nan
|
|
%fabs = call float @llvm.fabs.f32(float %sel)
|
|
%fneg.fabs = fneg float %fabs
|
|
store float %fabs, ptr %ptr ; external user on fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
; should fold to ret copysign(%x)
|
|
define nofpclass(inf) float @ret_nofpclass_inf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__copysign_positive_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_positive_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float 1.0)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[DOTNEG]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float -1.0)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can't fold to fneg(fabs(x))
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can fold to fneg(fabs(x))
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign_nnan_flag(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign_nnan_flag
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can fold to fneg(fabs(x))
|
|
define nofpclass(pnorm psub pzero) float @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(pzero psub pnorm) float @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan ninf float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan ninf float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can't fold to fneg(fabs(x))
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_nopositives_nonan_copysign(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_nopositives_nonan_copysign
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can't fold to fabs(x)
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can fold to fabs(x)
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign_nnan_flag(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign_nnan_flag
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; can fold to fabs(x)
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_nonan_copysign(float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_nonan_copysign
|
|
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs(i1 %cond, float %x, float %sign) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fabs.sign = call float @llvm.fabs.f32(float %sign)
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %fabs.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can fold to copysign %x
|
|
define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can fold to copysign %x
|
|
define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can't fold because it could have nan payload bits
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float +inf
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[SELECT]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can't fold because it could be nan
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float +inf
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[SELECT]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Could fold to copysign with constant
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float +inf
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Could fold to copysign %x with constant
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[DOTNEG]], float -inf
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_nnan_sign_known_positive_or_nan(float %x, float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan_sign_known_positive_or_nan
|
|
; CHECK-SAME: (float [[X:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %x, float %always.positive.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_nnan_sign_known_positive_or_nan__drop_ub_attrs(float %x, float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan_sign_known_positive_or_nan__drop_ub_attrs
|
|
; CHECK-SAME: (float [[X:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan noundef float @llvm.copysign.f32(float %x, float noundef nofpclass(zero) %always.positive.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_nnan_sign_known_negative_or_nan(float %x, float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan_sign_known_negative_or_nan
|
|
; CHECK-SAME: (float [[X:%.*]], float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %x, float %always.negative.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_nnan_sign_known_negative_or_nan__drop_ub_attrs(float %x, float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan_sign_known_negative_or_nan__drop_ub_attrs
|
|
; CHECK-SAME: (float [[X:%.*]], float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan float [[TMP1]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan noundef float @llvm.copysign.f32(float %x, float noundef nofpclass(zero) %always.negative.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Fold out copysign
|
|
define nofpclass(snan) float @copysign_nnan__known_positive__sign_known_positive_or_nan(float nofpclass(ninf nnorm nsub nzero) %known.positive, float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan__known_positive__sign_known_positive_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[KNOWN_POSITIVE:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[KNOWN_POSITIVE]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %known.positive, float %always.positive.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Fold out copysign
|
|
define nofpclass(snan) float @copysign_nnan__known_negative__sign_known_negative_or_nan(float nofpclass(pinf pnorm psub pzero) %known.negative, float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan__known_negative__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[KNOWN_NEGATIVE:%.*]], float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[KNOWN_NEGATIVE]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %known.negative, float %always.negative.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Convert to fabs
|
|
define nofpclass(snan) float @copysign_nnan__known_negative__sign_known_positive_or_nan(float nofpclass(pinf pnorm psub pzero) %known.negative, float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan__known_negative__sign_known_positive_or_nan
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[KNOWN_NEGATIVE:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.fabs.f32(float [[KNOWN_NEGATIVE]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %known.negative, float %always.positive.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Convert to fneg(fabs)
|
|
define nofpclass(snan) float @copysign_nnan__known_positive__sign_known_negative_or_nan(float nofpclass(ninf nnorm nsub nzero) %known.positive, float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_nnan__known_positive__sign_known_negative_or_nan
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[KNOWN_POSITIVE:%.*]], float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan float [[KNOWN_POSITIVE]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %known.positive, float %always.negative.or.nan)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Do nothing
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_negatives__select_clamp_neg_to_zero(float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_negatives__select_clamp_neg_to_zero
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[IS_LT_ZERO:%.*]] = fcmp olt float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_LT_ZERO]], float 0.000000e+00, float [[X]]
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%is.lt.zero = fcmp olt float %x, 0.0
|
|
%select = select i1 %is.lt.zero, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Can fold to ret %x, assumed to be nan
|
|
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_negatives__select_clamp_pos_to_zero(float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_negatives__select_clamp_pos_to_zero
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[IS_GT_ZERO:%.*]] = fcmp ogt float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_GT_ZERO]], float 0.000000e+00, float [[X]]
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%is.gt.zero = fcmp ogt float %x, 0.0
|
|
%select = select i1 %is.gt.zero, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Can fold to ret +0
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero(float noundef %x) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero
|
|
; CHECK-SAME: (float noundef [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%is.gt.zero = fcmp ogt float %x, 0.0
|
|
%select = select i1 %is.gt.zero, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Cannot fold due to undef
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero__maybe_undef(float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero__maybe_undef
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[IS_GT_ZERO:%.*]] = fcmp ogt float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_GT_ZERO]], float 0.000000e+00, float [[X]]
|
|
; CHECK-NEXT: ret float [[SELECT]]
|
|
;
|
|
%is.gt.zero = fcmp ogt float %x, 0.0
|
|
%select = select i1 %is.gt.zero, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Can fold to ret poison
|
|
define nofpclass(nan ninf nnorm nsub zero) float @ret_nofpclass_nan_negatives_zero__select_clamp_pos_to_zero(float %x) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf zero nsub nnorm) float @ret_nofpclass_nan_negatives_zero__select_clamp_pos_to_zero
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%is.gt.zero = fcmp ogt float %x, 0.0
|
|
%select = select i1 %is.gt.zero, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Can fold to ret %x, assumed to be nan
|
|
define nofpclass(ninf nnorm nsub zero) float @ret_nofpclass_negatives_zero__select_clamp_pos_to_zero(float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_nofpclass_negatives_zero__select_clamp_pos_to_zero
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%is.gt.zero = fcmp ogt float %x, 0.0
|
|
%select = select i1 %is.gt.zero, float 0.0, float %x
|
|
ret float %select
|
|
}
|
|
|
|
; Assume should allow folding ret %y
|
|
define nofpclass(inf) float @ret_nofpclass_noinfs__assumed_isinf__select_pinf_lhs(i1 %cond, float %x, float %y) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_noinfs__assumed_isinf__select_pinf_lhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[X_IS_INF:%.*]] = fcmp oeq float [[FABS_X]], +inf
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_INF]])
|
|
; CHECK-NEXT: ret float [[Y]]
|
|
;
|
|
%fabs.x = call float @llvm.fabs.f32(float %x)
|
|
%x.is.inf = fcmp oeq float %fabs.x, 0x7FF0000000000000
|
|
call void @llvm.assume(i1 %x.is.inf)
|
|
%select = select i1 %cond, float %x, float %y
|
|
ret float %select
|
|
}
|
|
|
|
; Ideally should be able to fold out everything after the exp2 call.
|
|
define nofpclass(nan inf nzero nsub nnorm) float @powr_issue64870(float nofpclass(nan inf) %x, float nofpclass(nan inf) %y) {
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @powr_issue64870
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[X:%.*]], float nofpclass(nan inf) [[Y:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[I:%.*]] = tail call float @llvm.fabs.f32(float [[X]])
|
|
; CHECK-NEXT: [[I1:%.*]] = tail call nnan float @llvm.log2.f32(float [[I]])
|
|
; CHECK-NEXT: [[I2:%.*]] = fmul nnan float [[I1]], [[Y]]
|
|
; CHECK-NEXT: [[I3:%.*]] = tail call nnan nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[I2]])
|
|
; CHECK-NEXT: [[I6:%.*]] = fcmp oeq float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[I7:%.*]] = select i1 [[I6]], float 0.000000e+00, float [[I3]]
|
|
; CHECK-NEXT: [[I8:%.*]] = fcmp oeq float [[Y]], 0.000000e+00
|
|
; CHECK-NEXT: [[I11:%.*]] = fcmp oeq float [[X]], 1.000000e+00
|
|
; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[I11]], i1 true, i1 [[I8]]
|
|
; CHECK-NEXT: [[I12:%.*]] = select i1 [[TMP0]], float 1.000000e+00, float [[I7]]
|
|
; CHECK-NEXT: ret float [[I12]]
|
|
;
|
|
entry:
|
|
%i = tail call float @llvm.fabs.f32(float %x)
|
|
%i1 = tail call float @llvm.log2.f32(float %i)
|
|
%i2 = fmul float %i1, %y
|
|
%i3 = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float %i2)
|
|
%i4 = fcmp olt float %y, 0.000000e+00
|
|
%i5 = select i1 %i4, float 0x7FF0000000000000, float 0.000000e+00
|
|
%i6 = fcmp oeq float %x, 0.000000e+00
|
|
%i7 = select i1 %i6, float %i5, float %i3
|
|
%i8 = fcmp oeq float %y, 0.000000e+00
|
|
%i9 = select i1 %i6, float 0x7FF8000000000000, float 1.000000e+00
|
|
%i10 = select i1 %i8, float %i9, float %i7
|
|
%i11 = fcmp oeq float %x, 1.000000e+00
|
|
%i12 = select i1 %i11, float 1.000000e+00, float %i10
|
|
%i13 = fcmp olt float %x, 0.000000e+00
|
|
%i14 = select i1 %i13, float 0x7FF8000000000000, float %i12
|
|
ret float %i14
|
|
}
|
|
|
|
; Different implementation of powr
|
|
define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2(float nofpclass(nan inf) %arg, float nofpclass(nan inf) %arg1) #0 {
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) {
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[I3:%.*]] = tail call nnan float @llvm.log2.f32(float [[ARG]])
|
|
; CHECK-NEXT: [[I5:%.*]] = fmul nnan float [[ARG1]], [[I3]]
|
|
; CHECK-NEXT: [[I6:%.*]] = tail call nnan nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[I5]])
|
|
; CHECK-NEXT: [[TMP0:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: [[I12:%.*]] = select i1 [[TMP0]], float 0.000000e+00, float [[I6]]
|
|
; CHECK-NEXT: ret float [[I12]]
|
|
;
|
|
bb:
|
|
%i = fcmp olt float %arg, 0.000000e+00
|
|
%i2 = select i1 %i, float 0x7FF8000000000000, float %arg
|
|
%i3 = tail call float @llvm.log2.f32(float noundef %i2) #2
|
|
%i4 = select i1 %i, float 0x7FF8000000000000, float %arg1
|
|
%i5 = fmul float %i4, %i3
|
|
%i6 = tail call noundef nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float noundef %i5)
|
|
%i7 = fcmp olt float %i4, 0.000000e+00
|
|
%i8 = select i1 %i7, float 0x7FF0000000000000, float 0.000000e+00
|
|
%i9 = fcmp ueq float %i4, 0.000000e+00
|
|
%i10 = fcmp oeq float %i2, 0.000000e+00
|
|
%i11 = select i1 %i9, float 0x7FF8000000000000, float %i8
|
|
%i12 = select i1 %i10, float %i11, float %i6
|
|
ret float %i12
|
|
}
|
|
|
|
; implementation of pow with some prunable cases
|
|
define nofpclass(nan inf) float @pow_f32(float nofpclass(nan inf) %arg, float nofpclass(nan inf) %arg1) #0 {
|
|
; CHECK-LABEL: define nofpclass(nan inf) float @pow_f32
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) {
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[I:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef [[ARG]])
|
|
; CHECK-NEXT: [[I2:%.*]] = tail call nnan float @llvm.log2.f32(float [[I]])
|
|
; CHECK-NEXT: [[I3:%.*]] = fmul nnan float [[I2]], [[ARG1]]
|
|
; CHECK-NEXT: [[I4:%.*]] = tail call nnan float @llvm.exp2.f32(float [[I3]])
|
|
; CHECK-NEXT: [[I5:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef [[ARG1]])
|
|
; CHECK-NEXT: [[I6:%.*]] = tail call float @llvm.trunc.f32(float noundef [[I5]])
|
|
; CHECK-NEXT: [[I7:%.*]] = fcmp oeq float [[I6]], [[I5]]
|
|
; CHECK-NEXT: [[I8:%.*]] = fmul nnan float [[I5]], 5.000000e-01
|
|
; CHECK-NEXT: [[I9:%.*]] = tail call float @llvm.trunc.f32(float noundef [[I8]])
|
|
; CHECK-NEXT: [[I10:%.*]] = fcmp une float [[I9]], [[I8]]
|
|
; CHECK-NEXT: [[I11:%.*]] = and i1 [[I7]], [[I10]]
|
|
; CHECK-NEXT: [[I12:%.*]] = select i1 [[I11]], float [[ARG]], float 1.000000e+00
|
|
; CHECK-NEXT: [[I13:%.*]] = tail call noundef float @llvm.copysign.f32(float noundef [[I4]], float noundef [[I12]])
|
|
; CHECK-NEXT: [[I17:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: [[TMP0:%.*]] = tail call nofpclass(nan sub norm) float @llvm.copysign.f32(float 0.000000e+00, float [[ARG]])
|
|
; CHECK-NEXT: [[I22:%.*]] = select i1 [[I11]], float [[TMP0]], float 0.000000e+00
|
|
; CHECK-NEXT: [[I23:%.*]] = select i1 [[I17]], float [[I22]], float [[I13]]
|
|
; CHECK-NEXT: [[I24:%.*]] = fcmp oeq float [[ARG]], 1.000000e+00
|
|
; CHECK-NEXT: [[I25:%.*]] = fcmp oeq float [[ARG1]], 0.000000e+00
|
|
; CHECK-NEXT: [[I26:%.*]] = or i1 [[I24]], [[I25]]
|
|
; CHECK-NEXT: [[I27:%.*]] = select i1 [[I26]], float 1.000000e+00, float [[I23]]
|
|
; CHECK-NEXT: ret float [[I27]]
|
|
;
|
|
bb:
|
|
%i = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef %arg)
|
|
%i2 = tail call float @llvm.log2.f32(float noundef %i)
|
|
%i3 = fmul float %i2, %arg1
|
|
%i4 = tail call noundef float @llvm.exp2.f32(float noundef %i3)
|
|
%i5 = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef %arg1)
|
|
%i6 = tail call float @llvm.trunc.f32(float noundef %i5)
|
|
%i7 = fcmp oeq float %i6, %i5
|
|
%i8 = fmul float %i5, 5.000000e-01
|
|
%i9 = tail call float @llvm.trunc.f32(float noundef %i8)
|
|
%i10 = fcmp une float %i9, %i8
|
|
%i11 = and i1 %i7, %i10
|
|
%i12 = select i1 %i11, float %arg, float 1.000000e+00
|
|
%i13 = tail call noundef float @llvm.copysign.f32(float noundef %i4, float noundef %i12)
|
|
%i14 = fcmp olt float %arg, 0.000000e+00
|
|
%i15 = select i1 %i7, float %i13, float 0x7FF8000000000000
|
|
%i16 = select i1 %i14, float %i15, float %i13
|
|
%i17 = fcmp oeq float %arg, 0.000000e+00
|
|
%i18 = fcmp olt float %arg1, 0.000000e+00
|
|
%i19 = xor i1 %i17, %i18
|
|
%i20 = select i1 %i19, float 0.000000e+00, float 0x7FF0000000000000
|
|
%i21 = select i1 %i11, float %arg, float 0.000000e+00
|
|
%i22 = tail call noundef nofpclass(nan sub norm) float @llvm.copysign.f32(float noundef %i20, float noundef %i21)
|
|
%i23 = select i1 %i17, float %i22, float %i16
|
|
%i24 = fcmp oeq float %arg, 1.000000e+00
|
|
%i25 = fcmp oeq float %arg1, 0.000000e+00
|
|
%i26 = or i1 %i24, %i25
|
|
%i27 = select i1 %i26, float 1.000000e+00, float %i23
|
|
ret float %i27
|
|
}
|
|
|
|
declare float @extern()
|
|
|
|
; Make sure nofpclass from arbitrary callsite is used, fold to %y
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_call_only_inf(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_call_only_inf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern()
|
|
; CHECK-NEXT: ret float [[Y]]
|
|
;
|
|
%must.be.inf = call nofpclass(nan norm zero sub) float @extern()
|
|
%select = select i1 %cond, float %must.be.inf, float %y
|
|
ret float %select
|
|
}
|
|
|
|
define nofpclass(pinf) float @ret_nofpclass_pinf__nofpclass_call_only_inf(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__nofpclass_call_only_inf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern()
|
|
; CHECK-NEXT: ret float -inf
|
|
;
|
|
%must.be.inf = call nofpclass(nan norm zero sub) float @extern()
|
|
ret float %must.be.inf
|
|
}
|
|
|
|
define nofpclass(ninf) float @ret_nofpclass_ninf__nofpclass_call_only_inf(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__nofpclass_call_only_inf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern()
|
|
; CHECK-NEXT: ret float +inf
|
|
;
|
|
%must.be.inf = call nofpclass(nan norm zero sub) float @extern()
|
|
ret float %must.be.inf
|
|
}
|
|
|
|
define nofpclass(nzero) float @ret_nofpclass_nzero__nofpclass_call_only_zero(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(nzero) float @ret_nofpclass_nzero__nofpclass_call_only_zero
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) float @extern()
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%must.be.zero = call nofpclass(nan sub norm inf) float @extern()
|
|
ret float %must.be.zero
|
|
}
|
|
|
|
define nofpclass(pzero) float @ret_nofpclass_pzero__nofpclass_call_only_zero(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(pzero) float @ret_nofpclass_pzero__nofpclass_call_only_zero
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) float @extern()
|
|
; CHECK-NEXT: ret float -0.000000e+00
|
|
;
|
|
%must.be.zero = call nofpclass(nan sub norm inf) float @extern()
|
|
ret float %must.be.zero
|
|
}
|
|
|
|
; Should not fold this, should not assume payload/sign bits are canonical
|
|
define nofpclass(qnan) float @ret_nofpclass_qnan__nofpclass_call_only_nan(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(qnan) float @ret_nofpclass_qnan__nofpclass_call_only_nan
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) float @extern()
|
|
; CHECK-NEXT: ret float [[MUST_BE_NAN]]
|
|
;
|
|
%must.be.nan = call nofpclass(inf norm zero sub) float @extern()
|
|
ret float %must.be.nan
|
|
}
|
|
|
|
; Should not fold this, should not assume payload/sign bits are canonical
|
|
define nofpclass(snan) float @ret_nofpclass_snan__nofpclass_call_only_nan(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @ret_nofpclass_snan__nofpclass_call_only_nan
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) float @extern()
|
|
; CHECK-NEXT: ret float [[MUST_BE_NAN]]
|
|
;
|
|
%must.be.nan = call nofpclass(inf norm zero sub) float @extern()
|
|
ret float %must.be.nan
|
|
}
|
|
|
|
; Assume call should allow folding this to %y
|
|
; TODO: Not working, multiple user problem.
|
|
define nofpclass(inf) float @ret_nofpclass_inf__select_assumed_call_result_only_inf(i1 %cond, float %y) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_assumed_call_result_only_inf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call float @extern()
|
|
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MUST_BE_INF]])
|
|
; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[FABS]], +inf
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[IS_INF]])
|
|
; CHECK-NEXT: ret float [[Y]]
|
|
;
|
|
%must.be.inf = call float @extern()
|
|
%fabs = call float @llvm.fabs.f32(float %must.be.inf)
|
|
%is.inf = fcmp oeq float %fabs, 0x7FF0000000000000
|
|
call void @llvm.assume(i1 %is.inf)
|
|
%select = select i1 %cond, float %must.be.inf, float %y
|
|
ret float %select
|
|
}
|
|
|
|
define nofpclass(inf) float @ret_nofpclass_inf__simple_phi_inf_or_unknown(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__simple_phi_inf_or_unknown
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND]], label [[BB0:%.*]], label [[RET:%.*]]
|
|
; CHECK: bb0:
|
|
; CHECK-NEXT: br label [[RET]]
|
|
; CHECK: ret:
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
entry:
|
|
br i1 %cond, label %bb0, label %ret
|
|
|
|
bb0:
|
|
br label %ret
|
|
|
|
ret:
|
|
%phi = phi float [ 0x7FF0000000000000, %entry ], [ %x, %bb0 ]
|
|
ret float %phi
|
|
}
|
|
|
|
declare i1 @loop.cond()
|
|
|
|
declare float @loop.func()
|
|
|
|
|
|
; Should be able to fold inf initial value to poison
|
|
define nofpclass(inf) float @ret_nofpclass_inf__phi_0(i1 %cond0, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__phi_0
|
|
; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PHI_LOOP:%.*]] = phi float [ poison, [[ENTRY:%.*]] ], [ [[LOOP_FUNC:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[LOOP_FUNC]] = call nofpclass(nan) float @loop.func()
|
|
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond()
|
|
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
|
|
; CHECK: ret:
|
|
; CHECK-NEXT: [[PHI_RET:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[PHI_LOOP]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret float [[PHI_RET]]
|
|
;
|
|
entry:
|
|
br i1 %cond0, label %loop, label %ret
|
|
|
|
loop:
|
|
%phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %loop.func, %loop ]
|
|
%loop.func = call nofpclass(nan) float @loop.func()
|
|
%loop.cond = call i1 @loop.cond()
|
|
br i1 %loop.cond, label %ret, label %loop
|
|
|
|
ret:
|
|
%phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
|
|
ret float %phi.ret
|
|
}
|
|
|
|
; fold to ret 0
|
|
define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_0(i1 %cond0, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_0
|
|
; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond()
|
|
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
|
|
; CHECK: ret:
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
entry:
|
|
br i1 %cond0, label %loop, label %ret
|
|
|
|
loop:
|
|
%phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
|
|
%loop.cond = call i1 @loop.cond()
|
|
br i1 %loop.cond, label %ret, label %loop
|
|
|
|
ret:
|
|
%phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
|
|
ret float %phi.ret
|
|
}
|
|
|
|
; fold to ret poison
|
|
define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_1(i1 %cond0, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_1
|
|
; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond()
|
|
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
|
|
; CHECK: ret:
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
entry:
|
|
br i1 %cond0, label %loop, label %ret
|
|
|
|
loop:
|
|
%phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
|
|
%loop.cond = call i1 @loop.cond()
|
|
br i1 %loop.cond, label %ret, label %loop
|
|
|
|
ret:
|
|
%phi.ret = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
|
|
ret float %phi.ret
|
|
}
|
|
|
|
; Should be able to fold inf initial values to poison
|
|
define nofpclass(inf) float @ret_nofpclass_inf__phi_switch_repeated_predecessor(i32 %switch, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__phi_switch_repeated_predecessor
|
|
; CHECK-SAME: (i32 [[SWITCH:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: switch i32 [[SWITCH]], label [[RET:%.*]] [
|
|
; CHECK-NEXT: i32 0, label [[LOOP:%.*]]
|
|
; CHECK-NEXT: i32 1, label [[LOOP]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond()
|
|
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
|
|
; CHECK: ret:
|
|
; CHECK-NEXT: [[PHI_RET:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[UNKNOWN]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret float [[PHI_RET]]
|
|
;
|
|
entry:
|
|
switch i32 %switch, label %ret [
|
|
i32 0, label %loop
|
|
i32 1, label %loop
|
|
]
|
|
|
|
loop:
|
|
%phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ 0x7FF0000000000000, %entry ], [ %unknown, %loop ]
|
|
%loop.cond = call i1 @loop.cond()
|
|
br i1 %loop.cond, label %ret, label %loop
|
|
|
|
ret:
|
|
%phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
|
|
ret float %phi.ret
|
|
}
|
|
|
|
; Simplify to arithmetic.fence %x
|
|
define nofpclass(inf) float @ret_nofpclass_inf__arithmetic_fence_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__arithmetic_fence_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[FENCE]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fence = call float @llvm.arithmetic.fence.f32(float %select)
|
|
ret float %fence
|
|
}
|
|
|
|
define nofpclass(snan) float @arithmetic_fence__noinf_callsite_param_attr_select_pinf_rhs(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @arithmetic_fence__noinf_callsite_param_attr_select_pinf_rhs
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float +inf
|
|
; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float nofpclass(inf) [[SELECT]])
|
|
; CHECK-NEXT: ret float [[FENCE]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF0000000000000
|
|
%fence = call float @llvm.arithmetic.fence.f32(float nofpclass(inf) %select)
|
|
ret float %fence
|
|
}
|
|
|
|
; Can simplify to %x
|
|
define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_pinf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_pinf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[MIN:%.*]] = call nsz float @llvm.minnum.f32(float [[X]], float +inf)
|
|
; CHECK-NEXT: ret float [[MIN]]
|
|
;
|
|
%min = call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000)
|
|
ret float %min
|
|
}
|
|
|
|
; Can fold to -inf
|
|
define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_ninf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_ninf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float -inf
|
|
;
|
|
%min = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
|
|
ret float %min
|
|
}
|
|
|
|
; Can simplify to %x
|
|
define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_ninf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_ninf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[MAX:%.*]] = call nsz float @llvm.maxnum.f32(float [[X]], float -inf)
|
|
; CHECK-NEXT: ret float [[MAX]]
|
|
;
|
|
%max = call float @llvm.maxnum.f32(float %x, float 0xFFF0000000000000)
|
|
ret float %max
|
|
}
|
|
|
|
; Can fold to +inf
|
|
define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_pinf(i1 %cond, float %x) {
|
|
; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_pinf
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
|
|
; CHECK-NEXT: ret float +inf
|
|
;
|
|
%max = call float @llvm.maxnum.f32(float %x, float 0x7FF0000000000000)
|
|
ret float %max
|
|
}
|
|
|
|
declare nofpclass(inf norm sub zero) float @returns_nan()
|
|
|
|
; %nan has multiple uses, but we should still know what class is is
|
|
; %allowing this to fold to a single select.
|
|
define nofpclass(nan) float @known_class_multiple_uses(i1 %cond0, i1 %cond1, i1 %cond2, float %unknown0, float %unknown1) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @known_class_multiple_uses
|
|
; CHECK-SAME: (i1 [[COND0:%.*]], i1 [[COND1:%.*]], i1 [[COND2:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
|
|
; CHECK-NEXT: [[NAN:%.*]] = call float @returns_nan()
|
|
; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[COND2]], float [[UNKNOWN0]], float [[UNKNOWN1]]
|
|
; CHECK-NEXT: ret float [[SELECT2]]
|
|
;
|
|
%nan = call float @returns_nan()
|
|
%select0 = select i1 %cond0, float %unknown0, float %nan
|
|
%select1 = select i1 %cond1, float %nan, float %unknown1
|
|
%select2 = select i1 %cond2, float %select0, float %select1
|
|
ret float %select2
|
|
}
|
|
|
|
; Do not overdefine the poison element to inf.
|
|
define nofpclass(ninf) <2 x float> @single_class_constant_partially_poison_pinf() {
|
|
; CHECK-LABEL: define nofpclass(ninf) <2 x float> @single_class_constant_partially_poison_pinf() {
|
|
; CHECK-NEXT: ret <2 x float> <float +inf, float poison>
|
|
;
|
|
ret <2 x float> <float 0x7FF0000000000000, float poison>
|
|
}
|
|
|
|
define nofpclass(ninf) <2 x float> @single_class_constant_partially_undef_pinf() {
|
|
; CHECK-LABEL: define nofpclass(ninf) <2 x float> @single_class_constant_partially_undef_pinf() {
|
|
; CHECK-NEXT: ret <2 x float> <float +inf, float undef>
|
|
;
|
|
ret <2 x float> <float 0x7FF0000000000000, float undef>
|
|
}
|
|
|
|
define nofpclass(zero) <3 x float> @mixed_sign_zero_splat_to_poison() {
|
|
; CHECK-LABEL: define nofpclass(zero) <3 x float> @mixed_sign_zero_splat_to_poison() {
|
|
; CHECK-NEXT: ret <3 x float> poison
|
|
;
|
|
ret <3 x float> <float 0.0, float -0.0, float poison>
|
|
}
|
|
|
|
define nofpclass(zero) <3 x float> @partially_defined_0_splat_to_poison() {
|
|
; CHECK-LABEL: define nofpclass(zero) <3 x float> @partially_defined_0_splat_to_poison() {
|
|
; CHECK-NEXT: ret <3 x float> poison
|
|
;
|
|
ret <3 x float> <float 0.0, float 0.0, float poison>
|
|
}
|
|
|
|
; The select must be 0, so the exp should fold to 1. This requires
|
|
; analysis of the select condition.
|
|
define nofpclass(nan) float @exp_select_must_be_0(float noundef %arg, float nofpclass(inf sub norm) %zero.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @exp_select_must_be_0
|
|
; CHECK-SAME: (float noundef [[ARG:%.*]], float nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: ret float 1.000000e+00
|
|
;
|
|
%not.zero = fcmp one float %arg, 0.0
|
|
%select = select i1 %not.zero, float %zero.or.nan, float %arg
|
|
%exp = call float @llvm.exp.f32(float %select)
|
|
ret float %exp
|
|
}
|
|
|
|
; The select must be 0, so the exp should fold to 1. This requires
|
|
; analysis of the select condition.
|
|
define nofpclass(nan) float @exp_select_must_be_0_commute(float noundef %arg, float nofpclass(inf sub norm) %zero.or.nan) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @exp_select_must_be_0_commute
|
|
; CHECK-SAME: (float noundef [[ARG:%.*]], float nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
|
|
; CHECK-NEXT: ret float 1.000000e+00
|
|
;
|
|
%is.zero = fcmp oeq float %arg, 0.0
|
|
%select = select i1 %is.zero, float %arg, float %zero.or.nan
|
|
%exp = call float @llvm.exp.f32(float %select)
|
|
ret float %exp
|
|
}
|
|
|
|
; Select has multiple uses, with the same user
|
|
define nofpclass(nan) float @ret_nonan_fmul_select_fmul_select_nan_multiple_use(i1 %cond, float noundef %x) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fmul_select_fmul_select_nan_multiple_use
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float noundef [[X:%.*]]) {
|
|
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[X]], [[X]]
|
|
; CHECK-NEXT: ret float [[FMUL]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF8000000000000
|
|
%fmul = fmul float %select, %select
|
|
ret float %fmul
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nonan_fmul_select_fmul_select_nan_multiple_use_commute(i1 %cond, float noundef %x) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fmul_select_fmul_select_nan_multiple_use_commute
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float noundef [[X:%.*]]) {
|
|
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[X]], [[X]]
|
|
; CHECK-NEXT: ret float [[FMUL]]
|
|
;
|
|
%select = select i1 %cond, float 0x7FF8000000000000, float %x
|
|
%fmul = fmul float %select, %select
|
|
ret float %fmul
|
|
}
|
|
|
|
; Select has a second, unrelated use
|
|
define nofpclass(nan) float @ret_nonan_fmul_select_nan_other_use(i1 %cond, float noundef %x, float %y, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fmul_select_nan_other_use
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float noundef [[X:%.*]], float [[Y:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float +qnan
|
|
; CHECK-NEXT: store float [[SELECT]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[NAN_USER:%.*]] = fmul nnan float [[X]], [[Y]]
|
|
; CHECK-NEXT: ret float [[NAN_USER]]
|
|
;
|
|
%select = select i1 %cond, float %x, float 0x7FF8000000000000
|
|
store float %select, ptr %ptr
|
|
%nan.user = fmul float %select, %y
|
|
ret float %nan.user
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nonan_fmul_select_nan_other_use_commute(i1 %cond, float noundef %x, float %y, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fmul_select_nan_other_use_commute
|
|
; CHECK-SAME: (i1 [[COND:%.*]], float noundef [[X:%.*]], float [[Y:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float +qnan, float [[X]]
|
|
; CHECK-NEXT: store float [[SELECT]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[NAN_USER:%.*]] = fmul nnan float [[X]], [[Y]]
|
|
; CHECK-NEXT: ret float [[NAN_USER]]
|
|
;
|
|
%select = select i1 %cond, float 0x7FF8000000000000, float %x
|
|
store float %select, ptr %ptr
|
|
%nan.user = fmul float %select, %y
|
|
ret float %nan.user
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_src_known_positive__sign_known_negative_multiple_use(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float nofpclass(nan pinf pnorm psub pzero) %always.negative, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_src_known_positive__sign_known_negative_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[ALWAYS_POSITIVE]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_src_known_negative__sign_known_negative_multiple_use(float nofpclass(nan pinf pnorm psub pzero) %always.negative0, float nofpclass(nan pinf pnorm psub pzero) %always.negative1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_src_known_negative__sign_known_negative_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE0:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE0]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE0]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative0, float %always.negative1)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(snan) float @copysign_src_known_positive__sign_known_positive_multiple_use(float nofpclass(nan ninf nnorm nsub nzero) %always.positive0, float nofpclass(nan ninf nnorm nsub nzero) %always.positive1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(snan) float @copysign_src_known_positive__sign_known_positive_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE0:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: store float [[ALWAYS_POSITIVE0]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE0]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive0, float %always.positive1)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan) float @ret_nonan__copysign_src_known_negative_or_nan__sign_known_negative_multiple_use(float nofpclass(pinf pnorm psub pzero) %always.negative0.or.nan, float nofpclass(nan pinf pnorm psub pzero) %always.negative1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__copysign_src_known_negative_or_nan__sign_known_negative_multiple_use
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE0_OR_NAN:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE0_OR_NAN]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE0_OR_NAN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative0.or.nan, float %always.negative1)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign__sign_known_negative_multiple_use(float %unknown, float nofpclass(nan pinf pnorm psub pzero) %always.negative, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign__sign_known_negative_multiple_use
|
|
; CHECK-SAME: (float [[UNKNOWN:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[UNKNOWN]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %unknown, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign__sign_known_positive_multiple_use(float %unknown, float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign__sign_known_positive_multiple_use
|
|
; CHECK-SAME: (float [[UNKNOWN:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %unknown, float %always.positive)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_only_negative__copysign__sign_known_negative_multiple_use(float %unknown, float nofpclass(nan pinf pnorm psub pzero) %always.negative, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative__copysign__sign_known_negative_multiple_use
|
|
; CHECK-SAME: (float [[UNKNOWN:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[UNKNOWN]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %unknown, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_only_negative__copysign__sign_known_positive_multiple_use(float %unknown, float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative__copysign__sign_known_positive_multiple_use
|
|
; CHECK-SAME: (float [[UNKNOWN:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %unknown, float %always.positive)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign_multiple_use(float %unknown.mag, float %unknown.sign, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign_multiple_use
|
|
; CHECK-SAME: (float [[UNKNOWN_MAG:%.*]], float [[UNKNOWN_SIGN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN_MAG]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %unknown.mag, float %unknown.sign)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_only_negative__copysign_multiple_use(float %unknown.mag, float %unknown.sign, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative__copysign_multiple_use
|
|
; CHECK-SAME: (float [[UNKNOWN_MAG:%.*]], float [[UNKNOWN_SIGN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN_MAG]], float [[UNKNOWN_SIGN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %unknown.mag, float %unknown.sign)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Fold to direct use of %always.positive
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Fold to direct use of %always.positive
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign_src_known_positive__sign_unknown_multiple_use(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign_src_known_positive__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_POSITIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Fold to direct use of %always.negative
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_only_negative__copysign_src_known_negative__sign_unknown(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative__copysign_src_known_negative__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Fold to direct use of %always.negative
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_only_negative__copysign_src_known_negative__sign_unknown_multiple_use(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative__copysign_src_known_negative__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Negative test
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign_src_known_negative__sign_unknown(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign_src_known_negative__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Negative test
|
|
define nofpclass(nan ninf nnorm nsub nzero) float @ret_only_positive__copysign_src_known_negative__sign_unknown_multiple_use(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive__copysign_src_known_negative__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Negative test
|
|
define nofpclass(nan pinf pnorm psub pzero) float @ret_only_negative__copysign_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative__copysign_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[ALWAYS_POSITIVE]]
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Could still be positive for +inf input
|
|
define nofpclass(nan nnorm nsub nzero) float @ret_only_positive_or_ninf__copysign_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan nzero nsub nnorm) float @ret_only_positive_or_ninf__copysign_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_POSITIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; The ninf flag gives the missing no-infs
|
|
define nofpclass(nan nnorm nsub nzero) float @ret_only_positive_or_ninf__copysign_ninf_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan nzero nsub nnorm) float @ret_only_positive_or_ninf__copysign_ninf_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
|
|
;
|
|
%copysign = call ninf float @llvm.copysign.f32(float %always.positive, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; The ninf flag gives the missing no-infs
|
|
define nofpclass(nan nnorm nsub nzero) float @ret_only_positive_or_ninf__copysign_ninf_src_known_positive__sign_unknown_multiple_use(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan nzero nsub nnorm) float @ret_only_positive_or_ninf__copysign_ninf_src_known_positive__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call ninf float @llvm.copysign.f32(float [[ALWAYS_POSITIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
|
|
;
|
|
%copysign = call ninf float @llvm.copysign.f32(float %always.positive, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; No pinf from argument
|
|
define nofpclass(nan nnorm nsub nzero) float @ret_only_positive_or_ninf__copysign_src_known_positive_no_inf__sign_unknown(float nofpclass(nan inf nnorm nsub nzero) %always.positive.no.inf, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan nzero nsub nnorm) float @ret_only_positive_or_ninf__copysign_src_known_positive_no_inf__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan inf nzero nsub nnorm) [[ALWAYS_POSITIVE_NO_INF:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_NO_INF]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.no.inf, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; No pinf from argument
|
|
define nofpclass(nan nnorm nsub nzero) float @ret_only_positive_or_ninf__copysign_src_known_positive_no_inf__sign_unknown_multiple_use(float nofpclass(nan inf nnorm nsub nzero) %always.positive.no.inf, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan nzero nsub nnorm) float @ret_only_positive_or_ninf__copysign_src_known_positive_no_inf__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan inf nzero nsub nnorm) [[ALWAYS_POSITIVE_NO_INF:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_NO_INF]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.no.inf, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan ninf nnorm nsub) float @ret_only_positive_or_zero__copysign_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub) %always.positive.or.zero, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_only_positive_or_zero__copysign_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_OR_ZERO]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.or.zero, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Ignore 0 mismatch with nsz
|
|
define nofpclass(nan ninf nnorm nsub) float @ret_only_positive_or_zero__copysign_nsz_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub) %always.positive.or.zero, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_only_positive_or_zero__copysign_nsz_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_ZERO]]
|
|
;
|
|
%copysign = call nsz float @llvm.copysign.f32(float %always.positive.or.zero, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Do not use nsz with multiple uses
|
|
define nofpclass(nan ninf nnorm nsub) float @ret_only_positive_or_zero__copysign_nsz_src_known_positive__sign_unknown_multiple_use(float nofpclass(nan ninf nnorm nsub) %always.positive.or.zero, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_only_positive_or_zero__copysign_nsz_src_known_positive__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nsz float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_OR_ZERO]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nsz float @llvm.copysign.f32(float %always.positive.or.zero, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(nan pinf pnorm psub) float @ret_only_negative_or_pzero__copysign_src_known_negative__sign_unknown(float nofpclass(nan pinf pnorm psub) %always.negative.or.zero, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf psub pnorm) float @ret_only_negative_or_pzero__copysign_src_known_negative__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_ZERO]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.zero, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Ignore 0 mismatch with nsz
|
|
define nofpclass(nan pinf pnorm psub) float @ret_only_negative_or_pzero__copysign_nsz_src_known_negative__sign_unknown(float nofpclass(nan pinf pnorm psub) %always.negative.or.zero, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf psub pnorm) float @ret_only_negative_or_pzero__copysign_nsz_src_known_negative__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_ZERO]]
|
|
;
|
|
%copysign = call nsz float @llvm.copysign.f32(float %always.negative.or.zero, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Do not use nsz with multiple uses
|
|
define nofpclass(nan pinf pnorm psub) float @ret_only_negative_or_pzero__copysign_nsz_src_known_negative__sign_unknown_multiple_use(float nofpclass(nan pinf pnorm psub) %always.negative.or.zero, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf psub pnorm) float @ret_only_negative_or_pzero__copysign_nsz_src_known_negative__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nsz float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_ZERO]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call nsz float @llvm.copysign.f32(float %always.negative.or.zero, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_or_nan__copysign_src_known_negative__sign_unknown(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_or_nan__copysign_src_known_negative__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_or_nan__copysign_src_known_negative__sign_unknown_multiple_use(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_or_nan__copysign_src_known_negative__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_or_nan__copysign_src_known_negative_or_nan__sign_unknown(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_or_nan__copysign_src_known_negative_or_nan__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_or_nan__copysign_src_known_negative_or_nan__sign_unknown_multiple_use(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_or_nan__copysign_src_known_negative_or_nan__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Take nnan from flag
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_or_nan__copysign_nnan_src_known_negative_or_nan__sign_unknown(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_or_nan__copysign_nnan_src_known_negative_or_nan__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Take nnan from flag
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_or_nan__copysign_nnan_src_known_negative_or_nan__sign_unknown_multiple_use(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_or_nan__copysign_nnan_src_known_negative_or_nan__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_positive_or_nan__copysign_src_known_positive__sign_unknown(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_positive_or_nan__copysign_src_known_positive__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_positive_or_nan__copysign_src_known_positive__sign_unknown_multiple_use(float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_positive_or_nan__copysign_src_known_positive__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_positive_or_nan__copysign_src_known_positive_or_nan__sign_unknown(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_positive_or_nan__copysign_src_known_positive_or_nan__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_positive_or_nan__copysign_src_known_positive_or_nan__sign_unknown_multiple_use(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_positive_or_nan__copysign_src_known_positive_or_nan__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Take nnan from flag
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_positive_or_nan__copysign_nnan_src_known_positive_or_nan__sign_unknown(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_positive_or_nan__copysign_nnan_src_known_positive_or_nan__sign_unknown
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
ret float %copysign
|
|
}
|
|
|
|
; Take nnan from flag
|
|
define nofpclass(pinf pnorm psub pzero) float @ret_only_positive_or_nan__copysign_nnan_src_known_positive_or_nan__sign_unknown_multiple_use(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float %unknown, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_positive_or_nan__copysign_nnan_src_known_positive_or_nan__sign_unknown_multiple_use
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[UNKNOWN]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%copysign = call nnan float @llvm.copysign.f32(float %always.negative.or.nan, float %unknown)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; We can only tell the sign bit is negative due to the ninf flag
|
|
define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_negative_or_pinf(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float nofpclass(nan pnorm psub pzero) %always.negative.or.pinf) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_negative_or_pinf
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float nofpclass(nan pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call ninf float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call ninf float @llvm.copysign.f32(float %always.negative.or.nan, float %always.negative.or.pinf)
|
|
ret float %copysign
|
|
}
|
|
|
|
; We can only tell the sign bit is negative due to the ninf flag
|
|
define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use(float nofpclass(pinf pnorm psub pzero) %always.negative.or.nan, float nofpclass(nan pnorm psub pzero) %always.negative.or.pinf, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_NAN:%.*]], float nofpclass(nan pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call ninf float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_NAN]], float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_NAN]]
|
|
;
|
|
%copysign = call ninf float @llvm.copysign.f32(float %always.negative.or.nan, float %always.negative.or.pinf)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; We can only tell the sign bit is positive due to the ninf flag
|
|
define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_positive_or_ninf(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, float nofpclass(nan nnorm nsub nzero) %always.negative.or.pinf) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_positive_or_ninf
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], float nofpclass(nan nzero nsub nnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call ninf float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_OR_NAN]], float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call ninf float @llvm.copysign.f32(float %always.positive.or.nan, float %always.negative.or.pinf)
|
|
ret float %copysign
|
|
}
|
|
|
|
; We can only tell the sign bit is positive due to the ninf flag
|
|
define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_positive_or_ninf__multiple_use(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, float nofpclass(nan nnorm nsub nzero) %always.negative.or.pinf, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__copysign_ninf__src_known_negative_or_nan__sign_known_positive_or_ninf__multiple_use
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], float nofpclass(nan nzero nsub nnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call ninf float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_OR_NAN]], float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
|
|
;
|
|
%copysign = call ninf float @llvm.copysign.f32(float %always.positive.or.nan, float %always.negative.or.pinf)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is negative due to no-inf return
|
|
define nofpclass(nan inf) float @ret_no_nan_no_inf__copysign__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use(float nofpclass(nan pnorm psub pzero) %always.negative.or.pinf, float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown0, float %unknown1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nan_no_inf__copysign__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_PINF]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.pinf, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; No-pinf result not sufficient
|
|
define nofpclass(nan pinf) float @ret_no_nan_no_pinf__copysign__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use(float nofpclass(nan pnorm psub pzero) %always.negative.or.pinf, float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown0, float %unknown1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan pinf) float @ret_no_nan_no_pinf__copysign__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.pinf, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; No-ninf result not sufficient
|
|
define nofpclass(nan ninf) float @ret_no_nan_no_ninf__copysign__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use(float nofpclass(nan pnorm psub pzero) %always.negative.or.pinf, float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown0, float %unknown1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan ninf) float @ret_no_nan_no_ninf__copysign__src_known_negative_or_nan__sign_known_negative_or_pinf__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pzero psub pnorm) [[ALWAYS_NEGATIVE_OR_PINF:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PINF]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.pinf, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is negative due to no-norm return
|
|
define nofpclass(nan norm) float @ret_no_nan_no_sub__copysign__src_known_negative_or_nan__sign_known_negative_or_pnorm__multiple_use(float nofpclass(nan pinf psub pzero) %always.negative.or.pnorm, float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown0, float %unknown1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan norm) float @ret_no_nan_no_sub__copysign__src_known_negative_or_nan__sign_known_negative_or_pnorm__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero psub) [[ALWAYS_NEGATIVE_OR_PNORM:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PNORM]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.pnorm, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is negative due to no-sub return
|
|
define nofpclass(nan sub) float @ret_no_nan_no_sub__copysign__src_known_negative_or_nan__sign_known_negative_or_psub__multiple_use(float nofpclass(nan pinf pnorm pzero) %always.negative.or.psub, float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown0, float %unknown1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan sub) float @ret_no_nan_no_sub__copysign__src_known_negative_or_nan__sign_known_negative_or_psub__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf pzero pnorm) [[ALWAYS_NEGATIVE_OR_PSUB:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PSUB]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.psub, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is negative due to no-zero return
|
|
define nofpclass(nan zero) float @ret_no_nan_no_zero__copysign__src_known_negative_or_nan__sign_known_negative_or_pzero__multiple_use(float nofpclass(nan pinf pnorm psub) %always.negative.or.pzero, float nofpclass(nan pinf pnorm psub pzero) %always.negative, float %unknown0, float %unknown1, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan zero) float @ret_no_nan_no_zero__copysign__src_known_negative_or_nan__sign_known_negative_or_pzero__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_PZERO:%.*]], float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_NEGATIVE_OR_PZERO]])
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.negative.or.pzero, float %always.negative)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is positive due to no-inf return
|
|
define nofpclass(nan inf) float @ret_no_nan_no_inf__copysign__src_known_positive_or_nan__sign_known_positive_or_ninf__multiple_use(float nofpclass(nan nnorm nsub nzero) %always.positive.or.ninf, float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nan_no_inf__copysign__src_known_positive_or_nan__sign_known_positive_or_ninf__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NINF:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NINF]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NINF]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.or.ninf, float %always.positive)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is positive due to no-norm return
|
|
define nofpclass(nan norm) float @ret_no_nan_no_norm__copysign__src_known_positive_or_nan__sign_known_positive_or_norm__multiple_use(float nofpclass(nan ninf nsub nzero) %always.positive.or.nnorm, float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan norm) float @ret_no_nan_no_norm__copysign__src_known_positive_or_nan__sign_known_positive_or_norm__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub) [[ALWAYS_POSITIVE_OR_NNORM:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NNORM]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.or.nnorm, float %always.positive)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is positive due to no-sub return
|
|
define nofpclass(nan sub) float @ret_no_nan_no_sub__copysign__src_known_positive_or_nan__sign_known_positive_or_sub__multiple_use(float nofpclass(nan ninf nnorm nzero) %always.positive.or.nsub, float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan sub) float @ret_no_nan_no_sub__copysign__src_known_positive_or_nan__sign_known_positive_or_sub__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nzero nnorm) [[ALWAYS_POSITIVE_OR_NSUB:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NSUB]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.or.nsub, float %always.positive)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
; Can infer sign bit is positive due to no-zero return
|
|
define nofpclass(nan zero) float @ret_no_nan_no_zero__copysign__src_known_positive_or_nan__sign_known_positive_or_zero__multiple_use(float nofpclass(nan ninf nnorm nsub) %always.positive.or.nzero, float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan zero) float @ret_no_nan_no_zero__copysign__src_known_positive_or_nan__sign_known_positive_or_zero__multiple_use
|
|
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_NZERO:%.*]], float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NZERO]])
|
|
; CHECK-NEXT: store float [[COPYSIGN]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[COPYSIGN]]
|
|
;
|
|
%copysign = call float @llvm.copysign.f32(float %always.positive.or.nzero, float %always.positive)
|
|
store float %copysign, ptr %ptr
|
|
ret float %copysign
|
|
}
|
|
|
|
define double @eigen_nofpclass_regression(ptr %ptr, double %arg) {
|
|
; CHECK-LABEL: define double @eigen_nofpclass_regression
|
|
; CHECK-SAME: (ptr [[PTR:%.*]], double [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[CALL2:%.*]] = call double @func(double 0.000000e+00, double 5.000000e+00, double -7.000000e+00)
|
|
; CHECK-NEXT: [[CALL4:%.*]] = call double @func(double 0.000000e+00, double 3.000000e+00, double -8.000000e+00)
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub double [[CALL2]], [[CALL4]]
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul double [[SUB]], [[ARG]]
|
|
; CHECK-NEXT: ret double [[MUL]]
|
|
;
|
|
%call2 = call double @func(double 0.000000e+00, double 5.000000e+00, double -7.000000e+00) #6
|
|
%call4 = call double @func(double 0.000000e+00, double 3.000000e+00, double -8.000000e+00) #6
|
|
%sub = fsub double %call2, %call4
|
|
%mul = fmul double %sub, %arg
|
|
ret double %mul
|
|
}
|
|
|
|
declare double @func(double nofpclass(nan inf nzero sub norm) %x, double nofpclass(nan inf zero sub nnorm) %v, double nofpclass(nan inf zero sub pnorm) %a)
|