Skip to content

Conversation

@arsenm
Copy link
Contributor

@arsenm arsenm commented Dec 15, 2025

This is similar to the identity value case; if we know we are
going to be multiplying by 0 and will get the sign right,
we can pull the constant into the select.

This is similar to the identity value case; if we know we are
going to be multiplying by 0 and will get the sign right,
we can pull the constant into the select.
Copy link
Contributor Author

arsenm commented Dec 15, 2025

@arsenm arsenm added the llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes label Dec 15, 2025 — with Graphite App
@arsenm arsenm added the floating-point Floating-point math label Dec 15, 2025 — with Graphite App
@arsenm arsenm marked this pull request as ready for review December 15, 2025 23:45
@llvmbot
Copy link
Member

llvmbot commented Dec 15, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Matt Arsenault (arsenm)

Changes

This is similar to the identity value case; if we know we are
going to be multiplying by 0 and will get the sign right,
we can pull the constant into the select.


Patch is 28.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/172380.diff

1 Files Affected:

  • (added) llvm/test/Transforms/InstCombine/select-fcmp-fmul-zero-absorbing-value.ll (+601)
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 %...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

floating-point Floating-point math llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants