-
Notifications
You must be signed in to change notification settings - Fork 15.5k
InstCombine: Add baseline test for fcmp-0-select combine #172380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
InstCombine: Add baseline test for fcmp-0-select combine #172380
Conversation
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 stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@llvm/pr-subscribers-llvm-transforms Author: Matt Arsenault (arsenm) ChangesThis is similar to the identity value case; if we know we are 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:
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]
|

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.