[llvm] [KnownFPClass] Refine `KnownFPClass::bitcast` deductions for `x86_fp80` (PR #224072)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 08:52:54 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-support

Author: Eric Ross (ZERICO2005)

<details>
<summary>Changes</summary>

Improves `KnownFPClass` deductions `i80` to `x86_fp80` bitcasts.

Non-canonical NaN's are treated as `fcSNan` if the quiet bit is known clear, and `fcQNan` if the quiet bit is known set.

AI Disclosure:
I used ChatGPT Codex (5.6 sol and Astra-6) and Claude (Sonnet/Opus 5) to help generate the tests and to review the code.


---

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


3 Files Affected:

- (modified) llvm/lib/Support/KnownFPClass.cpp (+80-1) 
- (added) llvm/test/Transforms/Attributor/nofpclass-bitcast-int-to-fp-x87.ll (+960) 
- (modified) llvm/unittests/Support/KnownFPClassTest.cpp (+104-22) 


``````````diff
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 48867ce3a6a6f..9e0614ec39637 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -264,7 +264,12 @@ KnownFPClass KnownFPClass::bitcast(const fltSemantics &FltSemantics,
   else if (Bits.isNegative())
     Known.signBitMustBeOne();
 
-  if (APFloat::isIEEELikeFP(FltSemantics)) {
+  switch (APFloatBase::SemanticsToEnum(FltSemantics)) {
+  case APFloatBase::S_IEEEhalf:
+  case APFloatBase::S_BFloat:
+  case APFloatBase::S_IEEEsingle:
+  case APFloatBase::S_IEEEdouble:
+  case APFloatBase::S_IEEEquad: {
     const unsigned MantissaBits = FltSemantics.precision - 1;
     const APInt ExponentMask = APInt::getBitsSet(
         FltSemantics.sizeInBits, MantissaBits, FltSemantics.sizeInBits - 1);
@@ -308,6 +313,80 @@ KnownFPClass KnownFPClass::bitcast(const fltSemantics &FltSemantics,
       Known.knownNot(fcSNan);
     else if (QuietBitKnownClear)
       Known.knownNot(fcQNan);
+
+    break;
+  }
+  case APFloatBase::S_x87DoubleExtended: {
+    // Layout of the x87 floating point type:
+    // [0:62] fraction
+    // [63] explicit integer bit
+    // [64:78] exponent
+    // [79] sign bit
+    // APFloat treats the x87 pseudo encodings as documented in
+    // fltSemantics::hasExplicitIntegerBit.
+    constexpr unsigned BitWidth = 80;
+    constexpr unsigned FractionBits = 63;
+    constexpr unsigned IntegerBitIndex = FractionBits;
+    const APInt FractionMask = APInt::getLowBitsSet(BitWidth, FractionBits);
+    const APInt ExponentMask =
+        APInt::getBitsSet(BitWidth, FractionBits + 1, BitWidth - 1);
+
+    const bool ExponentKnownAllZeros =
+        (Bits.Zero & ExponentMask) == ExponentMask;
+    const bool ExponentKnownAllOnes = (Bits.One & ExponentMask) == ExponentMask;
+    const bool ExponentKnownNotAllZeros = !(Bits.One & ExponentMask).isZero();
+    const bool ExponentKnownNotAllOnes = !(Bits.Zero & ExponentMask).isZero();
+    const bool FractionKnownAllZeros =
+        (Bits.Zero & FractionMask) == FractionMask;
+    const bool FractionKnownNotAllZeros = !(Bits.One & FractionMask).isZero();
+    const bool IntegerBitKnownSet = Bits.One[IntegerBitIndex];
+    const bool IntegerBitKnownClear = Bits.Zero[IntegerBitIndex];
+
+    // zero and subnormal require an exponent with all zero bits and a cleared
+    // integer bit.
+    if (ExponentKnownNotAllZeros || IntegerBitKnownSet)
+      Known.knownNot(fcZero | fcSubnormal);
+
+    // Zero requires a zero fraction.
+    if (FractionKnownNotAllZeros)
+      Known.knownNot(fcZero);
+
+    // Infinity requires an exponent with all one bits, a set integer bit, and
+    // a zero fraction.
+    if (ExponentKnownNotAllOnes || IntegerBitKnownClear ||
+        FractionKnownNotAllZeros)
+      Known.knownNot(fcInf);
+
+    // A normal x87 value has its integer bit set. A zero exponent with that
+    // bit set is the x87 pseudodenormal encoding, which APFloat treats as
+    // normal.
+    if (IntegerBitKnownClear || ExponentKnownAllOnes)
+      Known.knownNot(fcNormal);
+
+    // A subnormal has a nonzero fraction; NaNs are possible with a zero
+    // fraction through pseudoinfinity and unnormal encodings.
+    if (FractionKnownAllZeros)
+      Known.knownNot(fcSubnormal);
+
+    // We can rule out NaN if the value has all exponent bits set to zero, or
+    // if the value is a canonical normal or infinity.
+    if (ExponentKnownAllZeros ||
+        (IntegerBitKnownSet &&
+         (ExponentKnownNotAllOnes || FractionKnownAllZeros)))
+      Known.knownNot(fcNan);
+
+    const bool QuietBitKnownSet = Bits.One[FractionBits - 1];
+    const bool QuietBitKnownClear = Bits.Zero[FractionBits - 1];
+
+    if (QuietBitKnownSet)
+      Known.knownNot(fcSNan);
+    else if (QuietBitKnownClear)
+      Known.knownNot(fcQNan);
+
+    break;
+  }
+  default:
+    llvm_unreachable("unhandled supported type");
   }
 
   return Known;
diff --git a/llvm/test/Transforms/Attributor/nofpclass-bitcast-int-to-fp-x87.ll b/llvm/test/Transforms/Attributor/nofpclass-bitcast-int-to-fp-x87.ll
new file mode 100644
index 0000000000000..c1a9bbe3aec81
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nofpclass-bitcast-int-to-fp-x87.ll
@@ -0,0 +1,960 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal < %s | FileCheck %s
+
+;---------------------------------------------------------------------
+; Basic tests
+;---------------------------------------------------------------------
+
+define x86_fp80 @bitcast_to_x87_positive_one(i80 %arg) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) x86_fp80 @bitcast_to_x87_positive_one(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], 302222231531620438900736
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 302222231531620438900736
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0x3FFF8000000000000000
+  %orr = or i80 %and, u0x3FFF8000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87_negative_inf(i80 %arg) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) x86_fp80 @bitcast_to_x87_negative_inf(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -9223372036854775808
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], -9223372036854775808
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF8000000000000000
+  %orr = or i80 %and, u0xFFFF8000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87_all_ones(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) x86_fp80 @bitcast_to_x87_all_ones(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], -1
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, -1
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87_pos_signbit(i80 %arg) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) x86_fp80 @bitcast_to_x87_pos_signbit(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], 604462909807314587353087
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0x7FFFFFFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87_neg_signbit(i80 %arg) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) x86_fp80 @bitcast_to_x87_neg_signbit(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], -604462909807314587353088
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, u0x80000000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87_poison() {
+; CHECK-LABEL: define x86_fp80 @bitcast_to_x87_poison(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast i80 poison to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[CAST]]
+;
+  %cast = bitcast i80 poison to x86_fp80
+  ret x86_fp80 %cast
+}
+
+;---------------------------------------------------------------------
+; Exhuastive test of exponent-lsb, quiet-bit, integer-bit
+;---------------------------------------------------------------------
+
+; integer-bit unknown
+
+define x86_fp80 @bitcast_to_x87__unknown(i80 %arg) {
+; CHECK-LABEL: define x86_fp80 @bitcast_to_x87__unknown(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(inf) x86_fp80 @bitcast_to_x87__exp_lsb_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -18446744073709551617
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFEFFFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_set(i80 %arg) {
+; CHECK-LABEL: define nofpclass(zero sub) x86_fp80 @bitcast_to_x87__exp_lsb_set(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 18446744073709551616
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, u0x00010000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__quiet_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(qnan) x86_fp80 @bitcast_to_x87__quiet_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -4611686018427387905
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFFBFFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(qnan inf) x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -23058430092136939521
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFEBFFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(qnan zero sub) x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -4611686018427387905
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 18446744073709551616
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFFBFFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00010000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__quiet_bit_set(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero) x86_fp80 @bitcast_to_x87__quiet_bit_set(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 4611686018427387904
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, u0x00004000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_set(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero) x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_set(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -18446744073709551617
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 4611686018427387904
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFEFFFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00004000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_set(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub) x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_set(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 23058430092136939520
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, u0x00014000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+; integer-bit clear
+
+define x86_fp80 @bitcast_to_x87__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(inf norm) x86_fp80 @bitcast_to_x87__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -9223372036854775809
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF7FFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(inf norm) x86_fp80 @bitcast_to_x87__exp_lsb_clear__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -27670116110564327425
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFE7FFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_set__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) x86_fp80 @bitcast_to_x87__exp_lsb_set__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -9223372036854775809
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 18446744073709551616
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF7FFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00010000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__quiet_bit_clear__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(qnan inf norm) x86_fp80 @bitcast_to_x87__quiet_bit_clear__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -13835058055282163713
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF3FFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_clear__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(qnan inf norm) x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_clear__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -32281802128991715329
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 0
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFE3FFFFFFFFFFFFFFF
+  %orr = or i80 %and, 0
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_clear__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_clear__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -13835058055282163713
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 18446744073709551616
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF3FFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00010000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__quiet_bit_set__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero norm) x86_fp80 @bitcast_to_x87__quiet_bit_set__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -9223372036854775809
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 4611686018427387904
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF7FFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00004000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_set__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero norm) x86_fp80 @bitcast_to_x87__exp_lsb_clear__quiet_bit_set__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -27670116110564327425
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 4611686018427387904
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFE7FFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00004000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_set__integer_bit_clear(i80 %arg) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) x86_fp80 @bitcast_to_x87__exp_lsb_set__quiet_bit_set__integer_bit_clear(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -9223372036854775809
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 23058430092136939520
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFF7FFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00014000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+; integer_bit set
+
+define x86_fp80 @bitcast_to_x87__integer_bit_set(i80 %arg) {
+; CHECK-LABEL: define nofpclass(zero sub) x86_fp80 @bitcast_to_x87__integer_bit_set(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -1
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 9223372036854775808
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, -1
+  %orr = or i80 %and, u0x00008000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_fp80 %bitcast
+}
+
+define x86_fp80 @bitcast_to_x87__exp_lsb_clear__integer_bit_set(i80 %arg) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub) x86_fp80 @bitcast_to_x87__exp_lsb_clear__integer_bit_set(
+; CHECK-SAME: i80 [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[AND:%.*]] = and i80 [[ARG]], -18446744073709551617
+; CHECK-NEXT:    [[ORR:%.*]] = or i80 [[AND]], 9223372036854775808
+; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast i80 [[ORR]] to x86_fp80
+; CHECK-NEXT:    ret x86_fp80 [[BITCAST]]
+;
+  %and = and i80 %arg, u0xFFFEFFFFFFFFFFFFFFFF
+  %orr = or i80 %and, u0x00008000000000000000
+  %bitcast = bitcast i80 %orr to x86_fp80
+  ret x86_...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/224072


More information about the llvm-commits mailing list