| ; 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]], 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: [[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]], 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: [[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 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 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 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: [[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, <float 20.0, float 40.0> |
| %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, <float 0.0, float poison, float -0.0> |
| %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 |
| } |