[llvm] [KnownFPClass] Improve KnownFPClass::toKnownBits deductions for IEEE types (PR #223204)

Eric Ross via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 12 21:37:03 PDT 2026


https://github.com/ZERICO2005 created https://github.com/llvm/llvm-project/pull/223204

Allows `KnownFPClass::toKnownBits` to make deductions when the input is `fcSubnormal` or `fcNan`.


>From 5eaeacb76fdd42b4be580ac2f228091c907de2f7 Mon Sep 17 00:00:00 2001
From: zerico <zerico2005 at gmail.com>
Date: Sat, 12 Sep 2026 20:04:49 -0600
Subject: [PATCH 1/2] [InstCombine][NFC] Move bitcast from float tests into
 their own file

---
 .../InstCombine/known-bits-bitcast-from-fp.ll | 360 ++++++++++++++++++
 .../test/Transforms/InstCombine/known-bits.ll | 358 -----------------
 2 files changed, 360 insertions(+), 358 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll

diff --git a/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll b/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll
new file mode 100644
index 0000000000000..ff707b8824365
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll
@@ -0,0 +1,360 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+define i1 @test_sign_pos(float %x) {
+; CHECK-LABEL: @test_sign_pos(
+; CHECK-NEXT:    ret i1 true
+;
+  %fabs = call float @llvm.fabs.f32(float %x)
+  %y = bitcast float %fabs to i32
+  %sign = icmp sgt i32 %y, -1
+  ret i1 %sign
+}
+
+define i1 @test_sign_pos_half(half %x) {
+; CHECK-LABEL: @test_sign_pos_half(
+; CHECK-NEXT:    ret i1 true
+;
+  %fabs = call half @llvm.fabs.f16(half %x)
+  %y = bitcast half %fabs to i16
+  %sign = icmp sgt i16 %y, -1
+  ret i1 %sign
+}
+
+define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) {
+; CHECK-LABEL: @test_sign_pos_half_non_elementwise(
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32
+; CHECK-NEXT:    [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1
+; CHECK-NEXT:    ret i1 [[SIGN]]
+;
+  %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x)
+  %y = bitcast <2 x half> %fabs to i32
+  %sign = icmp sgt i32 %y, -1
+  ret i1 %sign
+}
+
+define i1 @test_sign_neg(float %x) {
+; CHECK-LABEL: @test_sign_neg(
+; CHECK-NEXT:    ret i1 true
+;
+  %fabs = call float @llvm.fabs.f32(float %x)
+  %fnabs = fneg float %fabs
+  %y = bitcast float %fnabs to i32
+  %sign = icmp slt i32 %y, 0
+  ret i1 %sign
+}
+
+define <2 x i1> @test_sign_pos_vec(<2 x float> %x) {
+; CHECK-LABEL: @test_sign_pos_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x)
+  %y = bitcast <2 x float> %fabs to <2 x i32>
+  %sign = icmp slt <2 x i32> %y, zeroinitializer
+  ret <2 x i1> %sign
+}
+
+define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_only(
+; CHECK-NEXT:    ret i32 2139095040
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2147483647
+  ret i32 %and
+}
+
+define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_only_bfloat(
+; CHECK-NEXT:    ret i16 32640
+;
+  %y = bitcast bfloat %x to i16
+  %and = and i16 %y, 32767
+  ret i16 %and
+}
+
+define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_only_ppc_fp128(
+; CHECK-NEXT:    [[TMP1:%.*]] = call ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 [[X:%.*]])
+; CHECK-NEXT:    [[AND:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128
+; CHECK-NEXT:    ret i128 [[AND]]
+;
+  %y = bitcast ppc_fp128 %x to i128
+  %and = and i128 %y, 170141183460469231731687303715884105727
+  ret i128 %and
+}
+
+define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) {
+; CHECK-LABEL: @test_zero_only(
+; CHECK-NEXT:    ret i32 0
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2147483647
+  ret i32 %and
+}
+
+define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) {
+; CHECK-LABEL: @test_zero_only_non_ieee(
+; CHECK-NEXT:    ret i80 0
+;
+  %y = bitcast x86_fp80 %x to i80
+  %and = and i80 %y, 604462909807314587353087
+  ret i80 %and
+}
+
+define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_nan_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2130706432
+  ret i32 %and
+}
+
+define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
+; CHECK-LABEL: @test_sub_zero_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2130706432
+  ret i32 %and
+}
+
+define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) {
+; CHECK-LABEL: @test_inf_zero_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 8388608
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 16777215
+  ret i32 %and
+}
+
+; Make sure that the signbit is cleared.
+define i32 @test_ninf_only(double %x) {
+; CHECK-LABEL: @test_ninf_only(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[X:%.*]], -inf
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    ret i32 0
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i32 0
+;
+  %cmp = fcmp oeq double %x, -inf
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %cast = bitcast double %x to i64
+  %trunc = trunc i64 %cast to i32
+  ret i32 %trunc
+
+if.else:
+  ret i32 0
+}
+
+define i1 @test_simplify_icmp(i32 %x) {
+; CHECK-LABEL: @test_simplify_icmp(
+; CHECK-NEXT:    ret i1 false
+;
+  %cast1 = uitofp i32 %x to double
+  %cast2 = bitcast double %cast1 to i64
+  %mask = and i64 %cast2, -140737488355328
+  %cmp = icmp eq i64 %mask, -1970324836974592
+  ret i1 %cmp
+}
+
+define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) {
+; CHECK-LABEL: @test_snan_quiet_bit1(
+; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 4194304
+; CHECK-NEXT:    ret i32 [[MASKED]]
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, 4194304
+  ret i32 %masked
+}
+
+define i32 @test_snan_quiet_bit2(float nofpclass(sub norm inf qnan) %x) {
+; CHECK-LABEL: @test_snan_quiet_bit2(
+; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 2097152
+; CHECK-NEXT:    ret i32 [[MASKED]]
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, 2097152
+  ret i32 %masked
+}
+
+define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) {
+; CHECK-LABEL: @test_qnan_quiet_bit1(
+; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 4194304
+; CHECK-NEXT:    ret i32 [[MASKED]]
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, 4194304
+  ret i32 %masked
+}
+
+define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) {
+; CHECK-LABEL: @test_qnan_quiet_bit2(
+; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 2097152
+; CHECK-NEXT:    ret i32 [[MASKED]]
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, 2097152
+  ret i32 %masked
+}
+
+define i16 @test_simplify_mask(i32 %ui, float %x) {
+; CHECK-LABEL: @test_simplify_mask(
+; CHECK-NEXT:    [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[CONV]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    ret i16 31744
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i16 0
+;
+  %conv = uitofp i32 %ui to float
+  %cmp = fcmp olt float %x, %conv
+  br i1 %cmp, label %if.else, label %if.end
+
+if.end:
+  %cast = bitcast float %conv to i32
+  %shr = lshr i32 %cast, 16
+  %trunc = trunc i32 %shr to i16
+  %and = and i16 %trunc, -32768
+  %or = or disjoint i16 %and, 31744
+  ret i16 %or
+
+if.else:
+  ret i16 0
+}
+
+define i1 @test_simplify_icmp2(double %x) {
+; CHECK-LABEL: @test_simplify_icmp2(
+; CHECK-NEXT:    [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[COND:%.*]] = fcmp oeq double [[ABS]], +inf
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i1 false
+;
+  %abs = tail call double @llvm.fabs.f64(double %x)
+  %cond = fcmp oeq double %abs, +inf
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %cast = bitcast double %x to i64
+  %cmp = icmp eq i64 %cast, 3458764513820540928
+  ret i1 %cmp
+
+if.else:
+  ret i1 false
+}
+
+define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) {
+; CHECK-LABEL: @test_snan_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 4194304
+  ret i32 %and
+}
+
+define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) {
+; CHECK-LABEL: @test_qnan_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 4194304
+  ret i32 %and
+}
+
+; Make sure that we don't crash when the use of x is unreachable.
+define i64 @pr92084(double %x) {
+; CHECK-LABEL: @pr92084(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then1:
+; CHECK-NEXT:    br i1 true, label [[IF_ELSE]], label [[IF_THEN2:%.*]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    ret i64 poison
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i64 0
+;
+  %cmp = fcmp uno double %x, 0.000000e+00
+  br i1 %cmp, label %if.then1, label %if.else
+
+if.then1:
+  br i1 %cmp, label %if.else, label %if.then2
+
+if.then2:
+  %cast = bitcast double %x to i64
+  %and = and i64 %cast, 1
+  ret i64 %and
+
+if.else:
+  ret i64 0
+}
+
+define i32 @test_none(float nofpclass(all) %x) {
+; CHECK-LABEL: @test_none(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 4194304
+  ret i32 %and
+}
+
+; We cannot make assumptions about the sign of result of sqrt
+; when the input is a negative value (except for -0).
+define i1 @pr92217() {
+; CHECK-LABEL: @pr92217(
+; CHECK-NEXT:    [[X:%.*]] = call float @llvm.sqrt.f32(float f0xF6F5F4F3)
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[Y]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %x = call float @llvm.sqrt.f32(float 0xC6DEBE9E60000000)
+  %y = bitcast float %x to i32
+  %cmp = icmp slt i32 %y, 0
+  ret i1 %cmp
+}
+
+define i1 @sqrt_negative_input(float nofpclass(nan zero pnorm psub pinf) %a) {
+; CHECK-LABEL: @sqrt_negative_input(
+; CHECK-NEXT:    [[X:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[Y]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %x = call float @llvm.sqrt.f32(float %a)
+  %y = bitcast float %x to i32
+  %cmp = icmp slt i32 %y, 0
+  ret i1 %cmp
+}
+
+define i1 @sqrt_negative_input_nnan(float nofpclass(nan zero pnorm psub pinf) %a) {
+; CHECK-LABEL: @sqrt_negative_input_nnan(
+; CHECK-NEXT:    ret i1 false
+;
+  %x = call nnan float @llvm.sqrt.f32(float %a)
+  %y = bitcast float %x to i32
+  %cmp = icmp slt i32 %y, 0
+  ret i1 %cmp
+}
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index f7d8ff7fffbbe..38f75d75e10d9 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -1465,364 +1465,6 @@ define i8 @nonzero_reduce_xor_vscale_odd(<vscale x 3 x i8> %xx) {
   ret i8 %r
 }
 
-define i1 @test_sign_pos(float %x) {
-; CHECK-LABEL: @test_sign_pos(
-; CHECK-NEXT:    ret i1 true
-;
-  %fabs = call float @llvm.fabs.f32(float %x)
-  %y = bitcast float %fabs to i32
-  %sign = icmp sgt i32 %y, -1
-  ret i1 %sign
-}
-
-define i1 @test_sign_pos_half(half %x) {
-; CHECK-LABEL: @test_sign_pos_half(
-; CHECK-NEXT:    ret i1 true
-;
-  %fabs = call half @llvm.fabs.f16(half %x)
-  %y = bitcast half %fabs to i16
-  %sign = icmp sgt i16 %y, -1
-  ret i1 %sign
-}
-
-define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) {
-; CHECK-LABEL: @test_sign_pos_half_non_elementwise(
-; CHECK-NEXT:    [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32
-; CHECK-NEXT:    [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1
-; CHECK-NEXT:    ret i1 [[SIGN]]
-;
-  %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x)
-  %y = bitcast <2 x half> %fabs to i32
-  %sign = icmp sgt i32 %y, -1
-  ret i1 %sign
-}
-
-define i1 @test_sign_neg(float %x) {
-; CHECK-LABEL: @test_sign_neg(
-; CHECK-NEXT:    ret i1 true
-;
-  %fabs = call float @llvm.fabs.f32(float %x)
-  %fnabs = fneg float %fabs
-  %y = bitcast float %fnabs to i32
-  %sign = icmp slt i32 %y, 0
-  ret i1 %sign
-}
-
-define <2 x i1> @test_sign_pos_vec(<2 x float> %x) {
-; CHECK-LABEL: @test_sign_pos_vec(
-; CHECK-NEXT:    ret <2 x i1> zeroinitializer
-;
-  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x)
-  %y = bitcast <2 x float> %fabs to <2 x i32>
-  %sign = icmp slt <2 x i32> %y, zeroinitializer
-  ret <2 x i1> %sign
-}
-
-define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
-; CHECK-LABEL: @test_inf_only(
-; CHECK-NEXT:    ret i32 2139095040
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 2147483647
-  ret i32 %and
-}
-
-define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) {
-; CHECK-LABEL: @test_inf_only_bfloat(
-; CHECK-NEXT:    ret i16 32640
-;
-  %y = bitcast bfloat %x to i16
-  %and = and i16 %y, 32767
-  ret i16 %and
-}
-
-define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) {
-; CHECK-LABEL: @test_inf_only_ppc_fp128(
-; CHECK-NEXT:    [[TMP1:%.*]] = call ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 [[X:%.*]])
-; CHECK-NEXT:    [[AND:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128
-; CHECK-NEXT:    ret i128 [[AND]]
-;
-  %y = bitcast ppc_fp128 %x to i128
-  %and = and i128 %y, 170141183460469231731687303715884105727
-  ret i128 %and
-}
-
-define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) {
-; CHECK-LABEL: @test_zero_only(
-; CHECK-NEXT:    ret i32 0
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 2147483647
-  ret i32 %and
-}
-
-define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) {
-; CHECK-LABEL: @test_zero_only_non_ieee(
-; CHECK-NEXT:    ret i80 0
-;
-  %y = bitcast x86_fp80 %x to i80
-  %and = and i80 %y, 604462909807314587353087
-  ret i80 %and
-}
-
-define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
-; CHECK-LABEL: @test_inf_nan_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
-; CHECK-NEXT:    ret i32 [[AND]]
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 2130706432
-  ret i32 %and
-}
-
-define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
-; CHECK-LABEL: @test_sub_zero_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
-; CHECK-NEXT:    ret i32 [[AND]]
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 2130706432
-  ret i32 %and
-}
-
-define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) {
-; CHECK-LABEL: @test_inf_zero_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 8388608
-; CHECK-NEXT:    ret i32 [[AND]]
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 16777215
-  ret i32 %and
-}
-
-; Make sure that the signbit is cleared.
-define i32 @test_ninf_only(double %x) {
-; CHECK-LABEL: @test_ninf_only(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[X:%.*]], -inf
-; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    ret i32 0
-; CHECK:       if.else:
-; CHECK-NEXT:    ret i32 0
-;
-  %cmp = fcmp oeq double %x, -inf
-  br i1 %cmp, label %if.then, label %if.else
-
-if.then:
-  %cast = bitcast double %x to i64
-  %trunc = trunc i64 %cast to i32
-  ret i32 %trunc
-
-if.else:
-  ret i32 0
-}
-
-define i1 @test_simplify_icmp(i32 %x) {
-; CHECK-LABEL: @test_simplify_icmp(
-; CHECK-NEXT:    ret i1 false
-;
-  %cast1 = uitofp i32 %x to double
-  %cast2 = bitcast double %cast1 to i64
-  %mask = and i64 %cast2, -140737488355328
-  %cmp = icmp eq i64 %mask, -1970324836974592
-  ret i1 %cmp
-}
-
-define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) {
-; CHECK-LABEL: @test_snan_quiet_bit1(
-; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 4194304
-; CHECK-NEXT:    ret i32 [[MASKED]]
-;
-  %bits = bitcast float %x to i32
-  %masked = and i32 %bits, 4194304
-  ret i32 %masked
-}
-
-define i32 @test_snan_quiet_bit2(float nofpclass(sub norm inf qnan) %x) {
-; CHECK-LABEL: @test_snan_quiet_bit2(
-; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 2097152
-; CHECK-NEXT:    ret i32 [[MASKED]]
-;
-  %bits = bitcast float %x to i32
-  %masked = and i32 %bits, 2097152
-  ret i32 %masked
-}
-
-define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) {
-; CHECK-LABEL: @test_qnan_quiet_bit1(
-; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 4194304
-; CHECK-NEXT:    ret i32 [[MASKED]]
-;
-  %bits = bitcast float %x to i32
-  %masked = and i32 %bits, 4194304
-  ret i32 %masked
-}
-
-define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) {
-; CHECK-LABEL: @test_qnan_quiet_bit2(
-; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 2097152
-; CHECK-NEXT:    ret i32 [[MASKED]]
-;
-  %bits = bitcast float %x to i32
-  %masked = and i32 %bits, 2097152
-  ret i32 %masked
-}
-
-define i16 @test_simplify_mask(i32 %ui, float %x) {
-; CHECK-LABEL: @test_simplify_mask(
-; CHECK-NEXT:    [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[CONV]]
-; CHECK-NEXT:    br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
-; CHECK:       if.end:
-; CHECK-NEXT:    ret i16 31744
-; CHECK:       if.else:
-; CHECK-NEXT:    ret i16 0
-;
-  %conv = uitofp i32 %ui to float
-  %cmp = fcmp olt float %x, %conv
-  br i1 %cmp, label %if.else, label %if.end
-
-if.end:
-  %cast = bitcast float %conv to i32
-  %shr = lshr i32 %cast, 16
-  %trunc = trunc i32 %shr to i16
-  %and = and i16 %trunc, -32768
-  %or = or disjoint i16 %and, 31744
-  ret i16 %or
-
-if.else:
-  ret i16 0
-}
-
-define i1 @test_simplify_icmp2(double %x) {
-; CHECK-LABEL: @test_simplify_icmp2(
-; CHECK-NEXT:    [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
-; CHECK-NEXT:    [[COND:%.*]] = fcmp oeq double [[ABS]], +inf
-; CHECK-NEXT:    br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    ret i1 false
-; CHECK:       if.else:
-; CHECK-NEXT:    ret i1 false
-;
-  %abs = tail call double @llvm.fabs.f64(double %x)
-  %cond = fcmp oeq double %abs, +inf
-  br i1 %cond, label %if.then, label %if.else
-
-if.then:
-  %cast = bitcast double %x to i64
-  %cmp = icmp eq i64 %cast, 3458764513820540928
-  ret i1 %cmp
-
-if.else:
-  ret i1 false
-}
-
-define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) {
-; CHECK-LABEL: @test_snan_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
-; CHECK-NEXT:    ret i32 [[AND]]
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 4194304
-  ret i32 %and
-}
-
-define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) {
-; CHECK-LABEL: @test_qnan_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
-; CHECK-NEXT:    ret i32 [[AND]]
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 4194304
-  ret i32 %and
-}
-
-; Make sure that we don't crash when the use of x is unreachable.
-define i64 @pr92084(double %x) {
-; CHECK-LABEL: @pr92084(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then1:
-; CHECK-NEXT:    br i1 true, label [[IF_ELSE]], label [[IF_THEN2:%.*]]
-; CHECK:       if.then2:
-; CHECK-NEXT:    ret i64 poison
-; CHECK:       if.else:
-; CHECK-NEXT:    ret i64 0
-;
-  %cmp = fcmp uno double %x, 0.000000e+00
-  br i1 %cmp, label %if.then1, label %if.else
-
-if.then1:
-  br i1 %cmp, label %if.else, label %if.then2
-
-if.then2:
-  %cast = bitcast double %x to i64
-  %and = and i64 %cast, 1
-  ret i64 %and
-
-if.else:
-  ret i64 0
-}
-
-define i32 @test_none(float nofpclass(all) %x) {
-; CHECK-LABEL: @test_none(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
-; CHECK-NEXT:    ret i32 [[AND]]
-;
-  %y = bitcast float %x to i32
-  %and = and i32 %y, 4194304
-  ret i32 %and
-}
-
-; We cannot make assumptions about the sign of result of sqrt
-; when the input is a negative value (except for -0).
-define i1 @pr92217() {
-; CHECK-LABEL: @pr92217(
-; CHECK-NEXT:    [[X:%.*]] = call float @llvm.sqrt.f32(float f0xF6F5F4F3)
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X]] to i32
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[Y]], 0
-; CHECK-NEXT:    ret i1 [[CMP]]
-;
-  %x = call float @llvm.sqrt.f32(float 0xC6DEBE9E60000000)
-  %y = bitcast float %x to i32
-  %cmp = icmp slt i32 %y, 0
-  ret i1 %cmp
-}
-
-define i1 @sqrt_negative_input(float nofpclass(nan zero pnorm psub pinf) %a) {
-; CHECK-LABEL: @sqrt_negative_input(
-; CHECK-NEXT:    [[X:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X]] to i32
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[Y]], 0
-; CHECK-NEXT:    ret i1 [[CMP]]
-;
-  %x = call float @llvm.sqrt.f32(float %a)
-  %y = bitcast float %x to i32
-  %cmp = icmp slt i32 %y, 0
-  ret i1 %cmp
-}
-
-define i1 @sqrt_negative_input_nnan(float nofpclass(nan zero pnorm psub pinf) %a) {
-; CHECK-LABEL: @sqrt_negative_input_nnan(
-; CHECK-NEXT:    ret i1 false
-;
-  %x = call nnan float @llvm.sqrt.f32(float %a)
-  %y = bitcast float %x to i32
-  %cmp = icmp slt i32 %y, 0
-  ret i1 %cmp
-}
-
 define i8 @test_icmp_add(i8 %n, i8 %n2, i8 %other) {
 ; CHECK-LABEL: @test_icmp_add(
 ; CHECK-NEXT:  entry:

>From c2af3b35631b55cd7306e66a72f6af1452d5405c Mon Sep 17 00:00:00 2001
From: zerico <zerico2005 at gmail.com>
Date: Fri, 4 Sep 2026 21:33:01 -0600
Subject: [PATCH 2/2] [KnownFPClass] Improve KnownFPClass::toKnownBits
 deductions for IEEE types

---
 llvm/lib/Support/KnownFPClass.cpp             |  71 ++++-
 .../InstCombine/known-bits-bitcast-from-fp.ll | 249 ++++++++++++++++--
 2 files changed, 302 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index b23a0dbbac4fb..af88358936d25 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -338,7 +338,68 @@ KnownBits KnownFPClass::toKnownBits(const fltSemantics &FltSemantics) const {
   if (!IsSupported(FltSemantics))
     return Known;
 
-  if (isKnownNever(fcNormal | fcSubnormal | fcNan)) {
+  switch (APFloat::SemanticsToEnum(FltSemantics)) {
+  case APFloatBase::S_IEEEhalf:
+  case APFloatBase::S_BFloat:
+  case APFloatBase::S_IEEEsingle:
+  case APFloatBase::S_IEEEdouble:
+  case APFloatBase::S_IEEEquad: {
+    // For ieee types, we cannot deduce anything if the source could be normal.
+    if (FPClasses & fcNormal)
+      break;
+
+    Known.setAllConflict();
+
+    const unsigned BitWidth = FltSemantics.sizeInBits;
+    const unsigned MantissaBits = FltSemantics.precision - 1;
+    const unsigned ExponentBits = BitWidth - MantissaBits - 1;
+
+    APInt MantissaMask = APInt::getLowBitsSet(BitWidth, MantissaBits);
+    APInt ExponentMask =
+        APInt::getBitsSet(BitWidth, MantissaBits, MantissaBits + ExponentBits);
+
+    const unsigned QuietBitIndex = MantissaBits - 1;
+    APInt PayloadMask = MantissaMask;
+    PayloadMask.clearBit(QuietBitIndex);
+
+    if (FPClasses & fcNan) {
+      // Exponent bits cannot be zeros.
+      Known.Zero &= ~ExponentMask;
+      // No individual payload bit is known.
+      Known.Zero &= ~PayloadMask;
+      Known.One &= ~PayloadMask;
+
+      if (FPClasses & fcQNan)
+        Known.Zero.clearBit(QuietBitIndex);
+      if (FPClasses & fcSNan)
+        Known.One.clearBit(QuietBitIndex);
+    }
+    if (FPClasses & fcInf) {
+      // Exponent bits cannot be zeros.
+      Known.Zero &= ~ExponentMask;
+      // Mantissa bits cannot be ones.
+      Known.One &= ~MantissaMask;
+    }
+    if (FPClasses & fcSubnormal) {
+      // Exponent bits cannot be ones.
+      Known.One &= ~ExponentMask;
+      // Unknown mantissa.
+      Known.One &= ~MantissaMask;
+      Known.Zero &= ~MantissaMask;
+    }
+    if (FPClasses & fcZero) {
+      // Exponent bits cannot be ones.
+      Known.One &= ~ExponentMask;
+      // Mantissa cannot be ones.
+      Known.One &= ~MantissaMask;
+    }
+
+    break;
+  }
+  case APFloatBase::S_x87DoubleExtended: {
+    if (!isKnownNever(fcNormal | fcSubnormal | fcNan))
+      break;
+
     Known.setAllConflict();
 
     if (FPClasses & fcInf)
@@ -349,10 +410,14 @@ KnownBits KnownFPClass::toKnownBits(const fltSemantics &FltSemantics) const {
       Known = Known.intersectWith(
           KnownBits::makeConstant(APInt::getZero(FltSemantics.sizeInBits)));
 
-    Known.Zero.clearSignBit();
-    Known.One.clearSignBit();
+    break;
+  }
+  default:
+    llvm_unreachable("unhandled supported semantics");
   }
 
+  Known.Zero.clearSignBit();
+  Known.One.clearSignBit();
   if (std::optional<bool> Sign = getSignBit()) {
     if (*Sign)
       Known.makeNegative();
diff --git a/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll b/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll
index ff707b8824365..10ea9fd50dca8 100644
--- a/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits-bitcast-from-fp.ll
@@ -104,9 +104,7 @@ define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) {
 
 define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
 ; CHECK-LABEL: @test_inf_nan_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 2130706432
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2130706432
@@ -115,9 +113,7 @@ define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
 
 define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
 ; CHECK-LABEL: @test_sub_zero_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2130706432
@@ -170,9 +166,7 @@ define i1 @test_simplify_icmp(i32 %x) {
 
 define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) {
 ; CHECK-LABEL: @test_snan_quiet_bit1(
-; CHECK-NEXT:    [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[MASKED:%.*]] = and i32 [[BITS]], 4194304
-; CHECK-NEXT:    ret i32 [[MASKED]]
+; CHECK-NEXT:    ret i32 0
 ;
   %bits = bitcast float %x to i32
   %masked = and i32 %bits, 4194304
@@ -212,6 +206,186 @@ define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) {
   ret i32 %masked
 }
 
+define i16 @test_f16_quiet_bit_clear(half nofpclass(qnan norm sub) %x) {
+; CHECK-LABEL: @test_f16_quiet_bit_clear(
+; CHECK-NEXT:    ret i16 0
+;
+  %bits = bitcast half %x to i16
+  %masked = and i16 %bits, u0x0200
+  ret i16 %masked
+}
+
+define i16 @test_f16_quiet_bit_set(half nofpclass(snan inf zero norm sub) %x) {
+; CHECK-LABEL: @test_f16_quiet_bit_set(
+; CHECK-NEXT:    ret i16 512
+;
+  %bits = bitcast half %x to i16
+  %masked = and i16 %bits, u0x0200
+  ret i16 %masked
+}
+
+define i16 @test_f16_all_zeros_exponent(half nofpclass(nan inf norm) %x) {
+; CHECK-LABEL: @test_f16_all_zeros_exponent(
+; CHECK-NEXT:    ret i16 0
+;
+  %bits = bitcast half %x to i16
+  %masked = and i16 %bits, u0x7C00
+  ret i16 %masked
+}
+
+define i16 @test_f16_all_ones_exponent(half nofpclass(zero norm sub) %x) {
+; CHECK-LABEL: @test_f16_all_ones_exponent(
+; CHECK-NEXT:    ret i16 31744
+;
+  %bits = bitcast half %x to i16
+  %masked = and i16 %bits, u0x7C00
+  ret i16 %masked
+}
+
+define i16 @test_bf16_quiet_bit_clear(bfloat nofpclass(qnan norm sub) %x) {
+; CHECK-LABEL: @test_bf16_quiet_bit_clear(
+; CHECK-NEXT:    ret i16 0
+;
+  %bits = bitcast bfloat %x to i16
+  %masked = and i16 %bits, u0x0040
+  ret i16 %masked
+}
+
+define i16 @test_bf16_quiet_bit_set(bfloat nofpclass(snan inf zero norm sub) %x) {
+; CHECK-LABEL: @test_bf16_quiet_bit_set(
+; CHECK-NEXT:    ret i16 64
+;
+  %bits = bitcast bfloat %x to i16
+  %masked = and i16 %bits, u0x0040
+  ret i16 %masked
+}
+
+define i16 @test_bf16_all_zeros_exponent(bfloat nofpclass(nan inf norm) %x) {
+; CHECK-LABEL: @test_bf16_all_zeros_exponent(
+; CHECK-NEXT:    ret i16 0
+;
+  %bits = bitcast bfloat %x to i16
+  %masked = and i16 %bits, u0x7F80
+  ret i16 %masked
+}
+
+define i16 @test_bf16_all_ones_exponent(bfloat nofpclass(zero norm sub) %x) {
+; CHECK-LABEL: @test_bf16_all_ones_exponent(
+; CHECK-NEXT:    ret i16 32640
+;
+  %bits = bitcast bfloat %x to i16
+  %masked = and i16 %bits, u0x7F80
+  ret i16 %masked
+}
+
+define i32 @test_f32_quiet_bit_clear(float nofpclass(qnan norm sub) %x) {
+; CHECK-LABEL: @test_f32_quiet_bit_clear(
+; CHECK-NEXT:    ret i32 0
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, u0x00400000
+  ret i32 %masked
+}
+
+define i32 @test_f32_quiet_bit_set(float nofpclass(snan inf zero norm sub) %x) {
+; CHECK-LABEL: @test_f32_quiet_bit_set(
+; CHECK-NEXT:    ret i32 4194304
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, u0x00400000
+  ret i32 %masked
+}
+
+define i32 @test_f32_all_zeros_exponent(float nofpclass(nan inf norm) %x) {
+; CHECK-LABEL: @test_f32_all_zeros_exponent(
+; CHECK-NEXT:    ret i32 0
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, u0x7F800000
+  ret i32 %masked
+}
+
+define i32 @test_f32_all_ones_exponent(float nofpclass(zero norm sub) %x) {
+; CHECK-LABEL: @test_f32_all_ones_exponent(
+; CHECK-NEXT:    ret i32 2139095040
+;
+  %bits = bitcast float %x to i32
+  %masked = and i32 %bits, u0x7F800000
+  ret i32 %masked
+}
+
+define i64 @test_f64_quiet_bit_clear(double nofpclass(qnan norm sub) %x) {
+; CHECK-LABEL: @test_f64_quiet_bit_clear(
+; CHECK-NEXT:    ret i64 0
+;
+  %bits = bitcast double %x to i64
+  %masked = and i64 %bits, u0x0008000000000000
+  ret i64 %masked
+}
+
+define i64 @test_f64_quiet_bit_set(double nofpclass(snan inf zero norm sub) %x) {
+; CHECK-LABEL: @test_f64_quiet_bit_set(
+; CHECK-NEXT:    ret i64 2251799813685248
+;
+  %bits = bitcast double %x to i64
+  %masked = and i64 %bits, u0x0008000000000000
+  ret i64 %masked
+}
+
+define i64 @test_f64_all_zeros_exponent(double nofpclass(nan inf norm) %x) {
+; CHECK-LABEL: @test_f64_all_zeros_exponent(
+; CHECK-NEXT:    ret i64 0
+;
+  %bits = bitcast double %x to i64
+  %masked = and i64 %bits, u0x7FF0000000000000
+  ret i64 %masked
+}
+
+define i64 @test_f64_all_ones_exponent(double nofpclass(zero norm sub) %x) {
+; CHECK-LABEL: @test_f64_all_ones_exponent(
+; CHECK-NEXT:    ret i64 9218868437227405312
+;
+  %bits = bitcast double %x to i64
+  %masked = and i64 %bits, u0x7FF0000000000000
+  ret i64 %masked
+}
+
+define i128 @test_f128_quiet_bit_clear(fp128 nofpclass(qnan norm sub) %x) {
+; CHECK-LABEL: @test_f128_quiet_bit_clear(
+; CHECK-NEXT:    ret i128 0
+;
+  %bits = bitcast fp128 %x to i128
+  %masked = and i128 %bits, u0x00008000000000000000000000000000
+  ret i128 %masked
+}
+
+define i128 @test_f128_quiet_bit_set(fp128 nofpclass(snan inf zero norm sub) %x) {
+; CHECK-LABEL: @test_f128_quiet_bit_set(
+; CHECK-NEXT:    ret i128 2596148429267413814265248164610048
+;
+  %bits = bitcast fp128 %x to i128
+  %masked = and i128 %bits, u0x00008000000000000000000000000000
+  ret i128 %masked
+}
+
+define i128 @test_f128_all_zeros_exponent(fp128 nofpclass(nan inf norm) %x) {
+; CHECK-LABEL: @test_f128_all_zeros_exponent(
+; CHECK-NEXT:    ret i128 0
+;
+  %bits = bitcast fp128 %x to i128
+  %masked = and i128 %bits, u0x7FFF0000000000000000000000000000
+  ret i128 %masked
+}
+
+define i128 @test_f128_all_ones_exponent(fp128 nofpclass(zero norm sub) %x) {
+; CHECK-LABEL: @test_f128_all_ones_exponent(
+; CHECK-NEXT:    ret i128 170135991163610696904058773219554885632
+;
+  %bits = bitcast fp128 %x to i128
+  %masked = and i128 %bits, u0x7FFF0000000000000000000000000000
+  ret i128 %masked
+}
+
 define i16 @test_simplify_mask(i32 %ui, float %x) {
 ; CHECK-LABEL: @test_simplify_mask(
 ; CHECK-NEXT:    [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float
@@ -261,25 +435,70 @@ if.else:
   ret i1 false
 }
 
-define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) {
+define i32 @test_snan_only(float nofpclass(qnan inf zero norm sub) %x) {
 ; CHECK-LABEL: @test_snan_only(
+; CHECK-NEXT:    ret i32 2139095040
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, u0x7FC00000
+  ret i32 %and
+}
+
+define i32 @test_qnan_only(float nofpclass(snan inf zero norm sub) %x) {
+; CHECK-LABEL: @test_qnan_only(
+; CHECK-NEXT:    ret i32 2143289344
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, u0x7FC00000
+  ret i32 %and
+}
+
+define i32 @test_nan_only_include_quiet_bit(float nofpclass(inf zero norm sub) %x) {
+; CHECK-LABEL: @test_nan_only_include_quiet_bit(
 ; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2143289344
 ; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %y = bitcast float %x to i32
-  %and = and i32 %y, 4194304
+  %and = and i32 %y, u0x7FC00000
   ret i32 %and
 }
 
-define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) {
-; CHECK-LABEL: @test_qnan_only(
+define i32 @test_nan_only_exclude_quiet_bit(float nofpclass(inf zero norm sub) %x) {
+; CHECK-LABEL: @test_nan_only_exclude_quiet_bit(
+; CHECK-NEXT:    ret i32 2139095040
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, u0x7F800000
+  ret i32 %and
+}
+
+define i32 @test_normal_only(float nofpclass(nan inf zero sub) %x) {
+; CHECK-LABEL: @test_normal_only(
 ; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 4194304
 ; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %y = bitcast float %x to i32
-  %and = and i32 %y, 4194304
+  %and = and i32 %y, u0x00400000
+  ret i32 %and
+}
+
+define i32 @test_pos_normal_only(float nofpclass(nan inf zero nnorm sub) %x) {
+; CHECK-LABEL: @test_pos_normal_only(
+; CHECK-NEXT:    ret i32 0
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, u0x80000000
+  ret i32 %and
+}
+
+define i32 @test_neg_normal_only(float nofpclass(nan inf zero pnorm sub) %x) {
+; CHECK-LABEL: @test_neg_normal_only(
+; CHECK-NEXT:    ret i32 -2147483648
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, u0x80000000
   ret i32 %and
 }
 



More information about the llvm-commits mailing list