[llvm] ca8f82b - [KnownFPClass] Restrict KnownFPClass::bitcast/toKnownBits deductions to verified FP semantics (#221133)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 16:10:05 PDT 2026
Author: Eric Ross
Date: 2026-09-12T17:10:00-06:00
New Revision: ca8f82b625494996d4f9f61f30d25b62a5660dca
URL: https://github.com/llvm/llvm-project/commit/ca8f82b625494996d4f9f61f30d25b62a5660dca
DIFF: https://github.com/llvm/llvm-project/commit/ca8f82b625494996d4f9f61f30d25b62a5660dca.diff
LOG: [KnownFPClass] Restrict KnownFPClass::bitcast/toKnownBits deductions to verified FP semantics (#221133)
`KnownFPClass::bitcast` and `KnownFPClass::toKnownBits` previously made
deductions for floating-point semantics whose bit representations had
not been verified.
I have made it so `KnownFPClass::bitcast` and
`KnownFPClass::toKnownBits` return `fcAllFlags`/unknown for any
`APFloat` semantics we have not verified. Currently, this prevents
potentially invalid deductions for `PPCDoubleDouble` (mostly in regards
to the signbit and endianess). It also allows these functions to be
"safely" used with the 4/6/8 bit floating point types since we
conservatively return unknown.
Currently the list of supported/verified semantics for both `bitcast`
and `toKnownBits` are:
```
IEEEhalf
BFloat
IEEEsingle
IEEEdouble
IEEEquad
x87DoubleExtended
```
Added:
Modified:
llvm/lib/Support/KnownFPClass.cpp
llvm/test/Transforms/InstCombine/known-bits.ll
llvm/unittests/Support/KnownFPClassTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 75636ffc73361..b23a0dbbac4fb 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -241,6 +241,23 @@ KnownFPClass KnownFPClass::bitcast(const fltSemantics &FltSemantics,
if (Bits.hasConflict())
return Known;
+ // Return unknown for types we have not validated.
+ auto IsSupported = [](const fltSemantics &Semantics) {
+ switch (APFloat::SemanticsToEnum(Semantics)) {
+ case APFloatBase::S_IEEEhalf:
+ case APFloatBase::S_BFloat:
+ case APFloatBase::S_IEEEsingle:
+ case APFloatBase::S_IEEEdouble:
+ case APFloatBase::S_IEEEquad:
+ case APFloatBase::S_x87DoubleExtended:
+ return true;
+ default:
+ return false;
+ }
+ };
+ if (!IsSupported(FltSemantics))
+ return Known;
+
// Transfer information from the sign bit.
if (Bits.isNonNegative())
Known.signBitMustBeZero();
@@ -304,6 +321,23 @@ KnownBits KnownFPClass::toKnownBits(const fltSemantics &FltSemantics) const {
if (FPClasses == fcNone)
return Known;
+ // Return unknown for types we have not validated.
+ auto IsSupported = [](const fltSemantics &Semantics) {
+ switch (APFloat::SemanticsToEnum(Semantics)) {
+ case APFloatBase::S_IEEEhalf:
+ case APFloatBase::S_BFloat:
+ case APFloatBase::S_IEEEsingle:
+ case APFloatBase::S_IEEEdouble:
+ case APFloatBase::S_IEEEquad:
+ case APFloatBase::S_x87DoubleExtended:
+ return true;
+ default:
+ return false;
+ }
+ };
+ if (!IsSupported(FltSemantics))
+ return Known;
+
if (isKnownNever(fcNormal | fcSubnormal | fcNan)) {
Known.setAllConflict();
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 8582d44fade63..f7d8ff7fffbbe 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -1539,7 +1539,9 @@ define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) {
define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) {
; CHECK-LABEL: @test_inf_only_ppc_fp128(
-; CHECK-NEXT: ret i128 9218868437227405312
+; 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
diff --git a/llvm/unittests/Support/KnownFPClassTest.cpp b/llvm/unittests/Support/KnownFPClassTest.cpp
index 4c3e1596b8e33..681b2d27fb547 100644
--- a/llvm/unittests/Support/KnownFPClassTest.cpp
+++ b/llvm/unittests/Support/KnownFPClassTest.cpp
@@ -128,4 +128,75 @@ TEST(KnownFPClassTest, BitcastConstant) {
}
}
+TEST(KnownFPClassTest, BitcastUnsupported) {
+ auto IsSupported = [](const fltSemantics &Semantics) {
+ switch (APFloat::SemanticsToEnum(Semantics)) {
+ case APFloatBase::S_IEEEhalf:
+ case APFloatBase::S_BFloat:
+ case APFloatBase::S_IEEEsingle:
+ case APFloatBase::S_IEEEdouble:
+ case APFloatBase::S_IEEEquad:
+ case APFloatBase::S_x87DoubleExtended:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
+ APFloat::Semantics SemanticsKind = static_cast<APFloat::Semantics>(I);
+ const fltSemantics &Semantics = APFloat::EnumToSemantics(SemanticsKind);
+
+ for (const APInt &ValueBits : {APInt::getZero(Semantics.sizeInBits),
+ APInt::getAllOnes(Semantics.sizeInBits)}) {
+ SCOPED_TRACE(testing::Message()
+ << "Semantics = " << I << ", bits = " << ValueBits);
+ KnownFPClass Known =
+ KnownFPClass::bitcast(Semantics, KnownBits::makeConstant(ValueBits));
+ if (IsSupported(Semantics)) {
+ // We should be able to make at least one deduction for "Supported"
+ // types.
+ EXPECT_FALSE(Known.isUnknown());
+ } else {
+ EXPECT_TRUE(Known.isUnknown());
+ }
+ }
+ }
+}
+
+TEST(KnownFPClassTest, ToKnownBitsUnsupported) {
+ auto IsSupported = [](const fltSemantics &Semantics) {
+ switch (APFloat::SemanticsToEnum(Semantics)) {
+ case APFloatBase::S_IEEEhalf:
+ case APFloatBase::S_BFloat:
+ case APFloatBase::S_IEEEsingle:
+ case APFloatBase::S_IEEEdouble:
+ case APFloatBase::S_IEEEquad:
+ case APFloatBase::S_x87DoubleExtended:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
+ APFloat::Semantics SemanticsKind = static_cast<APFloat::Semantics>(I);
+ const fltSemantics &Semantics = APFloat::EnumToSemantics(SemanticsKind);
+
+ for (FPClassTest FPClass : {fcPosZero, fcPosNormal}) {
+ SCOPED_TRACE(testing::Message()
+ << "Semantics = " << I << ", class = " << FPClass);
+ KnownBits Known = KnownFPClass(FPClass, false).toKnownBits(Semantics);
+ if (IsSupported(Semantics)) {
+ // The following expectations are true for all "supported" types.
+ EXPECT_TRUE(Known.isNonNegative());
+ if (FPClass == fcPosZero)
+ EXPECT_TRUE(Known.isZero());
+ } else {
+ EXPECT_TRUE(Known.isUnknown());
+ }
+ }
+ }
+}
+
} // end anonymous namespace
More information about the llvm-commits
mailing list