; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S -p=instcombine < %s | FileCheck %s define float @select_oeq_fmul_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_oeq_fmul_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float 0.000000e+00, float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_fabs_or_fabs_src_cmp_neg0(float %x) { ; CHECK-LABEL: define float @select_oeq_fmul_fabs_or_fabs_src_cmp_neg0( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float 0.000000e+00, float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, -0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fdiv_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_oeq_fdiv_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float 0.000000e+00, float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fdiv float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_fneg_or_fneg_src(float %x) { ; CHECK-LABEL: define float @select_oeq_fmul_fneg_or_fneg_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FNEG_X:%.*]] = fneg float [[X]] ; CHECK-NEXT: [[MUL_FNEG_X:%.*]] = fmul float [[X]], f0xCB800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FNEG_X]], float [[FNEG_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fneg.x = fneg float %x %mul.fneg.x = fmul float %fneg.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fneg.x, float %fneg.x ret float %select } define float @select_oeq_fmul_fneg_fabs_or_fneg_fabs_src(float %x) { ; CHECK-LABEL: define float @select_oeq_fmul_fneg_fabs_or_fneg_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[FNEG_FABS_X:%.*]] = fneg float [[FABS_X]] ; CHECK-NEXT: [[MUL_FNEG_FABS_X:%.*]] = fmul float [[FABS_X]], f0xCB800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FNEG_FABS_X]], float [[FNEG_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %fneg.fabs.x = fneg float %fabs.x %mul.fneg.fabs.x = fmul float %fneg.fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fneg.fabs.x, float %fneg.fabs.x ret float %select } ; Negative test, wrong fdiv operand define float @select_oeq_fdiv_swapped_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_oeq_fdiv_swapped_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fdiv float f0x4B800000, [[FABS_X]] ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fdiv float 0x4170000000000000, %fabs.x %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } ; Negative test, the fadd will not result in a 0 define float @select_fadd_fabs_or_fabs_tgt(float %x) { ; CHECK-LABEL: define float @select_fadd_fabs_or_fabs_tgt( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float 0.000000e+00, float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fadd float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float 0.0, float %fabs.x ret float %select } define float @select_fadd0_fabs_or_fabs_tgt(float %x) { ; CHECK-LABEL: define float @select_fadd0_fabs_or_fabs_tgt( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float 0.000000e+00, float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fadd float %fabs.x, 0.0 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float 0.0, float %fabs.x ret float %select } ; Negative test, select operands swapped define float @select_oeq_fmul_fabs_or_fabs_src_wrong_order(float %x) { ; CHECK-LABEL: define float @select_oeq_fmul_fabs_or_fabs_src_wrong_order( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[FABS_X]], float [[MUL_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %fabs.x, float %mul.fabs.x ret float %select } ; Negative test, not equality compare define float @select_olt_fmul_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_olt_fmul_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp olt float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp olt float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } ; Negative test, missing fabs on RHS define float @select_fmul_fabs_or_src(float %x) { ; CHECK-LABEL: define float @select_fmul_fabs_or_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float 0.000000e+00, float [[X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %x ret float %select } ; Negative test, missing fabs on fmul define float @select_fmul_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_fmul_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @fmul_fabs_neg_constant(float %x) { ; CHECK-LABEL: define float @fmul_fabs_neg_constant( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], -4.000000e+00 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, -4.0 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_fmul_nsz_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_fmul_nsz_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_X:%.*]] = fmul nsz float [[X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.x = fmul nsz float %x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.x, float %fabs.x ret float %select } define float @fmul_nsz_neg_constant(float %x) { ; CHECK-LABEL: define float @fmul_nsz_neg_constant( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[X]], -4.000000e+00 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %x, -4.0 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_ueq_fmul_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_ueq_fmul_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp ueq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.zero = fcmp ueq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } ; Unsafe with signaling nans. define float @select_one_fmul_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_one_fmul_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_NOT_ZERO:%.*]] = fcmp one float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_NOT_ZERO]], float [[FABS_X]], float [[MUL_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.not.zero = fcmp one float %x, 0.0 %select = select i1 %x.is.not.zero, float %fabs.x, float %mul.fabs.x ret float %select } ; OK with une and swapped arguments. define float @select_une_fmul_fabs_or_fabs_src(float %x) { ; CHECK-LABEL: define float @select_une_fmul_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_NOT_ZERO:%.*]] = fcmp une float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_NOT_ZERO]], float [[FABS_X]], float 0.000000e+00 ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.not.zero = fcmp une float %x, 0.0 %select = select i1 %x.is.not.zero, float %fabs.x, float %mul.fabs.x ret float %select } ; No fabs needed with NSZ on fmul define float @select_fmul_nsz(float %x) { ; CHECK-LABEL: define float @select_fmul_nsz( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: ret float [[X]] ; %mul.x = fmul nsz float %x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.x, float %x ret float %select } ; No fabs needed with NSZ on select define float @select_nsz(float %x) { ; CHECK-LABEL: define float @select_nsz( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: ret float [[X]] ; %mul.x = fmul float %x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select nsz i1 %x.is.zero, float %mul.x, float %x ret float %select } define float @degenerate_fmul_nan(float %x) { ; CHECK-LABEL: define float @degenerate_fmul_nan( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float +qnan, float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x7FF8000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @degenerate_fmul_posinf(float %x) { ; CHECK-LABEL: define float @degenerate_fmul_posinf( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], +inf ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x7FF0000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @degenerate_fmul_neginf(float %x) { ; CHECK-LABEL: define float @degenerate_fmul_neginf( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], -inf ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0xFFF0000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } ; nnan required on any operation, quieting required. define float @cmp_one_nnan_fabs(float %x) { ; CHECK-LABEL: define float @cmp_one_nnan_fabs( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call nnan float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul nnan float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_NOT_ZERO:%.*]] = fcmp one float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_NOT_ZERO]], float [[FABS_X]], float [[MUL_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call nnan float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.not.zero = fcmp one float %x, 0.0 %select = select i1 %x.is.not.zero, float %fabs.x, float %mul.fabs.x ret float %select } ; nnan required on any operation, quieting required. define float @cmp_one_nnan_fmul(float %x) { ; CHECK-LABEL: define float @cmp_one_nnan_fmul( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul nnan float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_NOT_ZERO:%.*]] = fcmp one float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_NOT_ZERO]], float [[FABS_X]], float [[MUL_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul nnan float %fabs.x, 0x4170000000000000 %x.is.not.zero = fcmp one float %x, 0.0 %select = select i1 %x.is.not.zero, float %fabs.x, float %mul.fabs.x ret float %select } ; nnan required on any operation, quieting required. define float @cmp_one_nnan_fcmp(float %x) { ; CHECK-LABEL: define float @cmp_one_nnan_fcmp( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_NOT_ZERO:%.*]] = fcmp nnan one float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_NOT_ZERO]], float [[FABS_X]], float [[MUL_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.not.zero = fcmp nnan one float %x, 0.0 %select = select i1 %x.is.not.zero, float %fabs.x, float %mul.fabs.x ret float %select } ; nnan required on any operation, quieting required. define float @cmp_one_nnan_select(float %x) { ; CHECK-LABEL: define float @cmp_one_nnan_select( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_NOT_ZERO:%.*]] = fcmp one float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select nnan i1 [[X_IS_NOT_ZERO]], float [[FABS_X]], float [[MUL_FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, 0x4170000000000000 %x.is.not.zero = fcmp one float %x, 0.0 %select = select nnan i1 %x.is.not.zero, float %fabs.x, float %mul.fabs.x ret float %select } define <2 x float> @select_oeq_fmul_fabs_or_fabs_src_vector(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @select_oeq_fmul_fabs_or_fabs_src_vector( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq <2 x float> [[X]], zeroinitializer ; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[X_IS_ZERO]], <2 x float> zeroinitializer, <2 x float> [[FABS_X]] ; CHECK-NEXT: ret <2 x float> [[SELECT]] ; %fabs.x = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x) %mul.fabs.x = fmul <2 x float> %fabs.x, %x.is.zero = fcmp oeq <2 x float> %x, zeroinitializer %select = select <2 x i1> %x.is.zero, <2 x float> %mul.fabs.x, <2 x float> %fabs.x ret <2 x float> %select } define <3 x float> @select_oeq_fmul_fabs_or_fabs_src_vector_mixed_sign_zero(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @select_oeq_fmul_fabs_or_fabs_src_vector_mixed_sign_zero( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call <3 x float> @llvm.fabs.v3f32(<3 x float> [[X]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq <3 x float> [[X]], zeroinitializer ; CHECK-NEXT: [[SELECT:%.*]] = select <3 x i1> [[X_IS_ZERO]], <3 x float> zeroinitializer, <3 x float> [[FABS_X]] ; CHECK-NEXT: ret <3 x float> [[SELECT]] ; %fabs.x = call <3 x float> @llvm.fabs.v3f32(<3 x float> %x) %mul.fabs.x = fmul <3 x float> %fabs.x, splat (float 0x4170000000000000) %x.is.zero = fcmp oeq <3 x float> %x, %select = select <3 x i1> %x.is.zero, <3 x float> %mul.fabs.x, <3 x float> %fabs.x ret <3 x float> %select } ; TODO: Should be able to handle this define float @test_ldexp_fabs(float %x, i32 %n) { ; CHECK-LABEL: define float @test_ldexp_fabs( ; CHECK-SAME: float [[X:%.*]], i32 [[N:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = call float @llvm.ldexp.f32.i32(float [[FABS_X]], i32 [[N]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = call float @llvm.ldexp.f32(float %fabs.x, i32 %n) %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_nonconst_unknown_fabs_or_fabs_src(float %x, float %y) { ; CHECK-LABEL: define float @select_oeq_fmul_nonconst_unknown_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], [[Y]] ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, %y %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_nonconst_ppos_fabs_or_fabs_src(float %x, float %y) { ; CHECK-LABEL: define float @select_oeq_fmul_nonconst_ppos_fabs_or_fabs_src( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X]], [[Y]] ; CHECK-NEXT: [[MUL_FABS_X1:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X1]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %fabs.y = call float @llvm.fabs.f32(float %y) %mul.fabs.x = fmul float %fabs.x, %fabs.y %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_copysign_or_copysign_src(float %x, float %sign) { ; CHECK-LABEL: define float @select_oeq_fmul_copysign_or_copysign_src( ; CHECK-SAME: float [[X:%.*]], float [[SIGN:%.*]]) { ; CHECK-NEXT: [[SIGN_X:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[SIGN]]) ; CHECK-NEXT: [[MUL_SIGN_X:%.*]] = fmul float [[SIGN_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_SIGN_X]], float [[SIGN_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %sign.x = call float @llvm.copysign.f32(float %x, float %sign) %mul.sign.x = fmul float %sign.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.sign.x, float %sign.x ret float %select } define float @select_oeq_fmul_copysign_or_src(float %x, float %sign) { ; CHECK-LABEL: define float @select_oeq_fmul_copysign_or_src( ; CHECK-SAME: float [[X:%.*]], float [[SIGN:%.*]]) { ; CHECK-NEXT: [[SIGN_X:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[SIGN]]) ; CHECK-NEXT: [[MUL_SIGN_X:%.*]] = fmul float [[SIGN_X]], f0x4B800000 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_SIGN_X]], float [[X]] ; CHECK-NEXT: ret float [[SELECT]] ; %sign.x = call float @llvm.copysign.f32(float %x, float %sign) %mul.sign.x = fmul float %sign.x, 0x4170000000000000 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.sign.x, float %x ret float %select } ; Negative test, +0 with a negative constant will still be -0 define float @select_oeq_fmul_neg_const(float %x) { ; CHECK-LABEL: define float @select_oeq_fmul_neg_const( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], -3.200000e+01 ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, -32.0 %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_unknown_var(float %x, float %unknown) { ; CHECK-LABEL: define float @select_oeq_fmul_unknown_var( ; CHECK-SAME: float [[X:%.*]], float [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], [[UNKNOWN]] ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, %unknown %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select } define float @select_oeq_fmul_known_positive_var(float %x, float nofpclass(ninf nsub nnorm nzero) %known.positive) { ; CHECK-LABEL: define float @select_oeq_fmul_known_positive_var( ; CHECK-SAME: float [[X:%.*]], float nofpclass(ninf nzero nsub nnorm) [[KNOWN_POSITIVE:%.*]]) { ; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], [[KNOWN_POSITIVE]] ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X]], 0.000000e+00 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[X_IS_ZERO]], float [[MUL_FABS_X]], float [[FABS_X]] ; CHECK-NEXT: ret float [[SELECT]] ; %fabs.x = call float @llvm.fabs.f32(float %x) %mul.fabs.x = fmul float %fabs.x, %known.positive %x.is.zero = fcmp oeq float %x, 0.0 %select = select i1 %x.is.zero, float %mul.fabs.x, float %fabs.x ret float %select }