diff --git a/llvm/test/Transforms/InstCombine/select-fcmp-fmul-zero-absorbing-value.ll b/llvm/test/Transforms/InstCombine/select-fcmp-fmul-zero-absorbing-value.ll new file mode 100644 index 0000000000000..660d2a0c0784e --- /dev/null +++ b/llvm/test/Transforms/InstCombine/select-fcmp-fmul-zero-absorbing-value.ll @@ -0,0 +1,601 @@ +; 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: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], 0x4170000000000000 +; 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, 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: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], 0x4170000000000000 +; 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, 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: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], 0x3E70000000000000 +; 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 %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]], 0xC170000000000000 +; 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]], 0xC170000000000000 +; 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 0x4170000000000000, [[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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], 0x4170000000000000 +; 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 [[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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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: [[MUL_FABS_X:%.*]] = fmul float [[FABS_X]], 0x4170000000000000 +; 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 [[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 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 0x7FF8000000000000, 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]], 0x7FF0000000000000 +; 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]], 0xFFF0000000000000 +; 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 float [[FABS_X]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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: [[MUL_FABS_X:%.*]] = fmul <2 x float> [[FABS_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> [[MUL_FABS_X]], <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: [[MUL_FABS_X:%.*]] = fmul <3 x float> [[FABS_X]], splat (float 0x4170000000000000) +; 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> [[MUL_FABS_X]], <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]], 0x4170000000000000 +; 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]], 0x4170000000000000 +; 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 +}