Skip to content

[llvm][NFC] APFloat: Add missing semantics to enum #117291

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

Merged

Conversation

matthias-springer
Copy link
Member

@matthias-springer matthias-springer commented Nov 22, 2024

  • Add missing semantics to the Semantics enum.
  • Move all documentation of the semantics to the header file.
  • Also rename some functions for consistency.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules llvm:support llvm:adt labels Nov 22, 2024
@matthias-springer matthias-springer changed the title [llvm][NFC] Add missing semantics to enum [llvm][NFC] APFloat: Add missing semantics to enum Nov 22, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 22, 2024

@llvm/pr-subscribers-llvm-support
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-llvm-adt

Author: Matthias Springer (matthias-springer)

Changes
  • Add missing semantics to the Semantics enum.
  • Move all documentation of the different semantics to the header file.
  • Rename the EnumToSemanatics to getSemantics.
  • Store enum value in fltSemantics so that there's one fewer place that must be updated when adding a new semantics.

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

5 Files Affected:

  • (modified) clang/include/clang/AST/Expr.h (+1-1)
  • (modified) clang/include/clang/AST/PropertiesBase.td (+2-2)
  • (modified) llvm/include/llvm/ADT/APFloat.h (+40-3)
  • (modified) llvm/lib/Support/APFloat.cpp (+45-99)
  • (modified) llvm/unittests/ADT/APFloatTest.cpp (+17-17)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 708c8656decbe0..22ce7bcbe181e3 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1672,7 +1672,7 @@ class FloatingLiteral : public Expr, private APFloatStorage {
 
   /// Return the APFloat semantics this literal uses.
   const llvm::fltSemantics &getSemantics() const {
-    return llvm::APFloatBase::EnumToSemantics(
+    return llvm::APFloatBase::getSemantics(
         static_cast<llvm::APFloatBase::Semantics>(
             FloatingLiteralBits.Semantics));
   }
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 42883b6419261c..7e417c7ef8fb24 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -282,7 +282,7 @@ let Class = PropertyTypeCase<APValue, "Float"> in {
     let Read = [{ node.getFloat().bitcastToAPInt() }];
   }
   def : Creator<[{
-    const llvm::fltSemantics &floatSema = llvm::APFloatBase::EnumToSemantics(
+    const llvm::fltSemantics &floatSema = llvm::APFloatBase::getSemantics(
         static_cast<llvm::APFloatBase::Semantics>(semantics));
     return APValue(llvm::APFloat(floatSema, value));
   }]>;
@@ -324,7 +324,7 @@ let Class = PropertyTypeCase<APValue, "ComplexFloat"> in {
     let Read = [{ node.getComplexFloatImag().bitcastToAPInt() }];
   }
   def : Creator<[{
-    const llvm::fltSemantics &sema = llvm::APFloatBase::EnumToSemantics(
+    const llvm::fltSemantics &sema = llvm::APFloatBase::getSemantics(
         static_cast<llvm::APFloatBase::Semantics>(semantics));
     return APValue(llvm::APFloat(sema, real),
                    llvm::APFloat(sema, imag));
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 4ca928bf4f49e3..3c90feeb16ae51 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -155,6 +155,15 @@ struct APFloatBase {
     S_IEEEsingle,
     S_IEEEdouble,
     S_IEEEquad,
+    // The IBM double-double semantics. Such a number consists of a pair of
+    // IEEE 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
+    // (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
+    // Therefore it has two 53-bit mantissa parts that aren't necessarily
+    // adjacent to each other, and two 11-bit exponents.
+    //
+    // Note: we need to make the value different from semBogus as otherwise
+    // an unsafe optimization may collapse both values to a single address,
+    // and we heavily rely on them having distinct addresses.
     S_PPCDoubleDouble,
     // 8-bit floating point number following IEEE-754 conventions with bit
     // layout S1E5M2 as described in https://arxiv.org/abs/2209.05433.
@@ -214,13 +223,41 @@ struct APFloatBase {
     // types, there are no infinity or NaN values. The format is detailed in
     // https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf
     S_Float4E2M1FN,
-
+    // TODO: Documentation is missing.
     S_x87DoubleExtended,
-    S_MaxSemantics = S_x87DoubleExtended,
+    // These are legacy semantics for the fallback, inaccrurate implementation
+    // of IBM double-double, if the accurate semPPCDoubleDouble doesn't handle
+    // the operation. It's equivalent to having an IEEE number with consecutive
+    // 106 bits of mantissa and 11 bits of exponent.
+    //
+    // It's not equivalent to IBM double-double. For example, a legit IBM
+    // double-double, 1 + epsilon:
+    //
+    // 1 + epsilon = 1 + (1 >> 1076)
+    //
+    // is not representable by a consecutive 106 bits of mantissa.
+    //
+    // Currently, these semantics are used in the following way:
+    //
+    //   semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
+    //   (64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
+    //   semPPCDoubleDoubleLegacy -> IEEE operations
+    //
+    // We use bitcastToAPInt() to get the bit representation (in APInt) of the
+    // underlying IEEEdouble, then use the APInt constructor to construct the
+    // legacy IEEE float.
+    //
+    // TODO: Implement all operations in semPPCDoubleDouble, and delete these
+    // semantics.
+    S_PPCDoubleDoubleLegacy,
+    // A Pseudo fltsemantic used to construct APFloats that cannot conflict
+    // with anything real.
+    S_Bogus,
+    S_MaxSemantics = S_Bogus,
   };
 
-  static const llvm::fltSemantics &EnumToSemantics(Semantics S);
   static Semantics SemanticsToEnum(const llvm::fltSemantics &Sem);
+  static const llvm::fltSemantics &getSemantics(Semantics S);
 
   static const fltSemantics &IEEEhalf() LLVM_READNONE;
   static const fltSemantics &BFloat() LLVM_READNONE;
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 81e297c3ab033e..25ca7a6b7fd370 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -101,6 +101,8 @@ enum class fltNanEncoding {
 
 /* Represents floating point arithmetic semantics.  */
 struct fltSemantics {
+  APFloat::Semantics name;
+
   /* The largest E such that 2^E is representable; this matches the
      definition of IEEE 754.  */
   APFloatBase::ExponentType maxExponent;
@@ -135,75 +137,54 @@ struct fltSemantics {
   }
 };
 
-static constexpr fltSemantics semIEEEhalf = {15, -14, 11, 16};
-static constexpr fltSemantics semBFloat = {127, -126, 8, 16};
-static constexpr fltSemantics semIEEEsingle = {127, -126, 24, 32};
-static constexpr fltSemantics semIEEEdouble = {1023, -1022, 53, 64};
-static constexpr fltSemantics semIEEEquad = {16383, -16382, 113, 128};
-static constexpr fltSemantics semFloat8E5M2 = {15, -14, 3, 8};
+static constexpr fltSemantics semIEEEhalf = {
+    APFloatBase::S_IEEEhalf, 15, -14, 11, 16};
+static constexpr fltSemantics semBFloat = {
+    APFloatBase::S_BFloat, 127, -126, 8, 16};
+static constexpr fltSemantics semIEEEsingle = {
+    APFloatBase::S_IEEEsingle, 127, -126, 24, 32};
+static constexpr fltSemantics semIEEEdouble = {
+    APFloatBase::S_IEEEdouble, 1023, -1022, 53, 64};
+static constexpr fltSemantics semIEEEquad = {
+    APFloatBase::S_IEEEquad, 16383, -16382, 113, 128};
+static constexpr fltSemantics semFloat8E5M2 = {
+    APFloatBase::S_Float8E5M2, 15, -14, 3, 8};
 static constexpr fltSemantics semFloat8E5M2FNUZ = {
-    15, -15, 3, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::NegativeZero};
-static constexpr fltSemantics semFloat8E4M3 = {7, -6, 4, 8};
+    APFloatBase::S_Float8E5M2FNUZ, 15, -15, 3, 8, fltNonfiniteBehavior::NanOnly,
+    fltNanEncoding::NegativeZero};
+static constexpr fltSemantics semFloat8E4M3 = {
+    APFloatBase::S_Float8E4M3, 7, -6, 4, 8};
 static constexpr fltSemantics semFloat8E4M3FN = {
-    8, -6, 4, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::AllOnes};
+    APFloatBase::S_Float8E4M3FN, 8, -6, 4, 8, fltNonfiniteBehavior::NanOnly,
+    fltNanEncoding::AllOnes};
 static constexpr fltSemantics semFloat8E4M3FNUZ = {
-    7, -7, 4, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::NegativeZero};
+    APFloatBase::S_Float8E4M3FNUZ, 7, -7, 4, 8, fltNonfiniteBehavior::NanOnly,
+    fltNanEncoding::NegativeZero};
 static constexpr fltSemantics semFloat8E4M3B11FNUZ = {
-    4, -10, 4, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::NegativeZero};
-static constexpr fltSemantics semFloat8E3M4 = {3, -2, 5, 8};
-static constexpr fltSemantics semFloatTF32 = {127, -126, 11, 19};
+    APFloatBase::S_Float8E4M3B11FNUZ, 4, -10, 4, 8, fltNonfiniteBehavior::NanOnly,
+    fltNanEncoding::NegativeZero};
+static constexpr fltSemantics semFloat8E3M4 = {
+    APFloatBase::S_Float8E3M4, 3, -2, 5, 8};
+static constexpr fltSemantics semFloatTF32 = {
+    APFloatBase::S_FloatTF32, 127, -126, 11, 19};
 static constexpr fltSemantics semFloat8E8M0FNU = {
-    127,   -127, 1, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::AllOnes,
-    false, false};
-
+    APFloatBase::S_Float8E8M0FNU, 127, -127, 1, 8, fltNonfiniteBehavior::NanOnly,
+    fltNanEncoding::AllOnes, false, false};
 static constexpr fltSemantics semFloat6E3M2FN = {
-    4, -2, 3, 6, fltNonfiniteBehavior::FiniteOnly};
+    APFloatBase::S_Float6E3M2FN, 4, -2, 3, 6, fltNonfiniteBehavior::FiniteOnly};
 static constexpr fltSemantics semFloat6E2M3FN = {
-    2, 0, 4, 6, fltNonfiniteBehavior::FiniteOnly};
+    APFloatBase::S_Float6E2M3FN, 2, 0, 4, 6, fltNonfiniteBehavior::FiniteOnly};
 static constexpr fltSemantics semFloat4E2M1FN = {
-    2, 0, 2, 4, fltNonfiniteBehavior::FiniteOnly};
-static constexpr fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};
-static constexpr fltSemantics semBogus = {0, 0, 0, 0};
-
-/* The IBM double-double semantics. Such a number consists of a pair of IEEE
-   64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
-   (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
-   Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent
-   to each other, and two 11-bit exponents.
-
-   Note: we need to make the value different from semBogus as otherwise
-   an unsafe optimization may collapse both values to a single address,
-   and we heavily rely on them having distinct addresses.             */
-static constexpr fltSemantics semPPCDoubleDouble = {-1, 0, 0, 128};
-
-/* These are legacy semantics for the fallback, inaccrurate implementation of
-   IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the
-   operation. It's equivalent to having an IEEE number with consecutive 106
-   bits of mantissa and 11 bits of exponent.
-
-   It's not equivalent to IBM double-double. For example, a legit IBM
-   double-double, 1 + epsilon:
+    APFloatBase::S_Float4E2M1FN, 2, 0, 2, 4, fltNonfiniteBehavior::FiniteOnly};
+static constexpr fltSemantics semX87DoubleExtended = {
+    APFloatBase::S_x87DoubleExtended, 16383, -16382, 64, 80};
+static constexpr fltSemantics semBogus = {APFloatBase::S_Bogus, 0, 0, 0, 0};
+static constexpr fltSemantics semPPCDoubleDouble = {APFloatBase::S_PPCDoubleDouble, -1, 0, 0, 128};
 
-     1 + epsilon = 1 + (1 >> 1076)
-
-   is not representable by a consecutive 106 bits of mantissa.
-
-   Currently, these semantics are used in the following way:
-
-     semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
-     (64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
-     semPPCDoubleDoubleLegacy -> IEEE operations
-
-   We use bitcastToAPInt() to get the bit representation (in APInt) of the
-   underlying IEEEdouble, then use the APInt constructor to construct the
-   legacy IEEE float.
-
-   TODO: Implement all operations in semPPCDoubleDouble, and delete these
-   semantics.  */
-static constexpr fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53,
+static constexpr fltSemantics semPPCDoubleDoubleLegacy = {APFloatBase::S_PPCDoubleDoubleLegacy, 1023, -1022 + 53,
                                                           53 + 53, 128};
 
-const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
+const llvm::fltSemantics &APFloatBase::getSemantics(Semantics S) {
   switch (S) {
   case S_IEEEhalf:
     return IEEEhalf();
@@ -217,6 +198,8 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
     return IEEEquad();
   case S_PPCDoubleDouble:
     return PPCDoubleDouble();
+  case S_PPCDoubleDoubleLegacy:
+    return semPPCDoubleDoubleLegacy;
   case S_Float8E5M2:
     return Float8E5M2();
   case S_Float8E5M2FNUZ:
@@ -243,52 +226,15 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
     return Float4E2M1FN();
   case S_x87DoubleExtended:
     return x87DoubleExtended();
+  case S_Bogus:
+    return Bogus();
   }
   llvm_unreachable("Unrecognised floating semantics");
 }
 
 APFloatBase::Semantics
 APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) {
-  if (&Sem == &llvm::APFloat::IEEEhalf())
-    return S_IEEEhalf;
-  else if (&Sem == &llvm::APFloat::BFloat())
-    return S_BFloat;
-  else if (&Sem == &llvm::APFloat::IEEEsingle())
-    return S_IEEEsingle;
-  else if (&Sem == &llvm::APFloat::IEEEdouble())
-    return S_IEEEdouble;
-  else if (&Sem == &llvm::APFloat::IEEEquad())
-    return S_IEEEquad;
-  else if (&Sem == &llvm::APFloat::PPCDoubleDouble())
-    return S_PPCDoubleDouble;
-  else if (&Sem == &llvm::APFloat::Float8E5M2())
-    return S_Float8E5M2;
-  else if (&Sem == &llvm::APFloat::Float8E5M2FNUZ())
-    return S_Float8E5M2FNUZ;
-  else if (&Sem == &llvm::APFloat::Float8E4M3())
-    return S_Float8E4M3;
-  else if (&Sem == &llvm::APFloat::Float8E4M3FN())
-    return S_Float8E4M3FN;
-  else if (&Sem == &llvm::APFloat::Float8E4M3FNUZ())
-    return S_Float8E4M3FNUZ;
-  else if (&Sem == &llvm::APFloat::Float8E4M3B11FNUZ())
-    return S_Float8E4M3B11FNUZ;
-  else if (&Sem == &llvm::APFloat::Float8E3M4())
-    return S_Float8E3M4;
-  else if (&Sem == &llvm::APFloat::FloatTF32())
-    return S_FloatTF32;
-  else if (&Sem == &llvm::APFloat::Float8E8M0FNU())
-    return S_Float8E8M0FNU;
-  else if (&Sem == &llvm::APFloat::Float6E3M2FN())
-    return S_Float6E3M2FN;
-  else if (&Sem == &llvm::APFloat::Float6E2M3FN())
-    return S_Float6E2M3FN;
-  else if (&Sem == &llvm::APFloat::Float4E2M1FN())
-    return S_Float4E2M1FN;
-  else if (&Sem == &llvm::APFloat::x87DoubleExtended())
-    return S_x87DoubleExtended;
-  else
-    llvm_unreachable("Unknown floating semantics");
+  return Sem.name;
 }
 
 const fltSemantics &APFloatBase::IEEEhalf() { return semIEEEhalf; }
@@ -3038,7 +2984,7 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
                                         unsigned sigPartCount, int exp,
                                         roundingMode rounding_mode) {
   unsigned int parts, pow5PartCount;
-  fltSemantics calcSemantics = { 32767, -32767, 0, 0 };
+  fltSemantics calcSemantics = { APFloatBase::S_MaxSemantics, 32767, -32767, 0, 0 };
   integerPart pow5Parts[maxPowerOfFiveParts];
   bool isNearest;
 
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index f291c814886d35..5be9b1e9ad0a63 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -822,7 +822,7 @@ TEST(APFloatTest, Denormal) {
 TEST(APFloatTest, IsSmallestNormalized) {
   for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
     const fltSemantics &Semantics =
-        APFloat::EnumToSemantics(static_cast<APFloat::Semantics>(I));
+        APFloat::getSemantics(static_cast<APFloat::Semantics>(I));
 
     // For Float8E8M0FNU format, the below cases are tested
     // through Float8E8M0FNUSmallest and Float8E8M0FNUNext tests.
@@ -2276,7 +2276,7 @@ TEST(APFloatTest, copySign) {
   // For floating-point formats with unsigned 0, copySign() to a zero is a noop
   for (APFloat::Semantics S :
        {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
-    const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
+    const llvm::fltSemantics &Sem = APFloat::getSemantics(S);
     EXPECT_TRUE(APFloat::getZero(Sem).bitwiseIsEqual(
         APFloat::copySign(APFloat::getZero(Sem), APFloat(-1.0))));
     EXPECT_TRUE(APFloat::getNaN(Sem, true).bitwiseIsEqual(
@@ -2406,7 +2406,7 @@ TEST(APFloatTest, Float8UZConvert) {
   for (APFloat::Semantics S :
        {APFloat::S_Float8E5M2FNUZ, APFloat::S_Float8E4M3FNUZ,
         APFloat::S_Float8E4M3B11FNUZ}) {
-    const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
+    const llvm::fltSemantics &Sem = APFloat::getSemantics(S);
     SCOPED_TRACE("Semantics = " + std::to_string(S));
     for (auto [toTest, expectedRes] : toNaNTests) {
       llvm::SmallString<16> value;
@@ -2561,7 +2561,7 @@ TEST(APFloatTest, isInfinity) {
 
   for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
     const fltSemantics &Semantics =
-        APFloat::EnumToSemantics(static_cast<APFloat::Semantics>(I));
+        APFloat::getSemantics(static_cast<APFloat::Semantics>(I));
     if (APFloat::semanticsHasInf(Semantics)) {
       EXPECT_TRUE(APFloat::getInf(Semantics).isInfinity());
     }
@@ -2579,7 +2579,7 @@ TEST(APFloatTest, isNaN) {
 
   for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
     const fltSemantics &Semantics =
-        APFloat::EnumToSemantics(static_cast<APFloat::Semantics>(I));
+        APFloat::getSemantics(static_cast<APFloat::Semantics>(I));
     if (APFloat::semanticsHasNaN(Semantics)) {
       EXPECT_TRUE(APFloat::getNaN(Semantics).isNaN());
     }
@@ -5348,7 +5348,7 @@ TEST(APFloatTest, Float8ExhaustivePair) {
   for (APFloat::Semantics Sem :
        {APFloat::S_Float8E4M3FN, APFloat::S_Float8E5M2FNUZ,
         APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
-    const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem);
+    const llvm::fltSemantics &S = APFloat::getSemantics(Sem);
     for (int i = 0; i < 256; i++) {
       for (int j = 0; j < 256; j++) {
         SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) +
@@ -5427,7 +5427,7 @@ TEST(APFloatTest, Float8ExhaustivePair) {
 TEST(APFloatTest, Float8E8M0FNUExhaustivePair) {
   // Test each pair of 8-bit values for Float8E8M0FNU format
   APFloat::Semantics Sem = APFloat::S_Float8E8M0FNU;
-  const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem);
+  const llvm::fltSemantics &S = APFloat::getSemantics(Sem);
   for (int i = 0; i < 256; i++) {
     for (int j = 0; j < 256; j++) {
       SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) +
@@ -5526,7 +5526,7 @@ TEST(APFloatTest, Float6ExhaustivePair) {
   // Test each pair of 6-bit floats with non-standard semantics
   for (APFloat::Semantics Sem :
        {APFloat::S_Float6E3M2FN, APFloat::S_Float6E2M3FN}) {
-    const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem);
+    const llvm::fltSemantics &S = APFloat::getSemantics(Sem);
     for (int i = 1; i < 64; i++) {
       for (int j = 1; j < 64; j++) {
         SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) +
@@ -5609,7 +5609,7 @@ TEST(APFloatTest, Float6ExhaustivePair) {
 TEST(APFloatTest, Float4ExhaustivePair) {
   // Test each pair of 4-bit floats with non-standard semantics
   for (APFloat::Semantics Sem : {APFloat::S_Float4E2M1FN}) {
-    const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem);
+    const llvm::fltSemantics &S = APFloat::getSemantics(Sem);
     for (int i = 0; i < 16; i++) {
       for (int j = 0; j < 16; j++) {
         SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) +
@@ -6137,7 +6137,7 @@ TEST(APFloatTest, UnsignedZeroArithmeticSpecial) {
   // The IEEE round towards negative rule doesn't apply
   for (APFloat::Semantics S :
        {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
-    const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
+    const llvm::fltSemantics &Sem = APFloat::getSemantics(S);
     APFloat test = APFloat::getSmallest(Sem);
     APFloat rhs = test;
     EXPECT_EQ(test.subtract(rhs, APFloat::rmTowardNegative), APFloat::opOK);
@@ -6293,7 +6293,7 @@ TEST(APFloatTest, Float8UnsignedZeroExhaustive) {
 TEST(APFloatTest, Float8E4M3FNUZNext) {
   for (APFloat::Semantics S :
        {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
-    const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
+    const llvm::fltSemantics &Sem = APFloat::getSemantics(S);
     APFloat test(Sem, APFloat::uninitialized);
     APFloat expected(Sem, APFloat::uninitialized);
 
@@ -6348,7 +6348,7 @@ TEST(APFloatTest, Float8E4M3FNUZNext) {
 TEST(APFloatTest, Float8E4M3FNUZChangeSign) {
   for (APFloat::Semantics S :
        {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
-    const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
+    const llvm::fltSemantics &Sem = APFloat::getSemantics(S);
     APFloat test = APFloat(Sem, "1.0");
     APFloat expected = APFloat(Sem, "-1.0");
     test.changeSign();
@@ -6551,14 +6551,14 @@ TEST(APFloatTest, F8ToString) {
     SCOPED_TRACE("Semantics=" + std::to_string(S));
     for (int i = 0; i < 256; i++) {
       SCOPED_TRACE("i=" + std::to_string(i));
-      APFloat test(APFloat::EnumToSemantics(S), APInt(8, i));
+      APFloat test(APFloat::getSemantics(S), APInt(8, i));
       llvm::SmallString<128> str;
       test.toString(str);
 
       if (test.isNaN()) {
         EXPECT_EQ(str, "NaN");
       } else {
-        APFloat test2(APFloat::EnumToSemantics(S), str);
+        APFloat test2(APFloat::getSemantics(S), str);
         EXPECT_TRUE(test.bitwiseIsEqual...
[truncated]

Copy link

github-actions bot commented Nov 22, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@matthias-springer
Copy link
Member Author

There are various places in APFloat.h and APFloat.cpp that contain switch-case / if-check sequences for checking the type of semantics. I'm trying to reduce these. What I had in mind:

  • Removing APFloatBase::IEEEhalf(), APFloatBase::BFloat(), ..., and use a single APFloatBase::getSemantics instead. (But there are a lot of places that call IEEEHalf etc.)
  • Add function pointers APInt (*convertToAPInt)(const APFloat &) and APFloat (*initFromAPInt)(const APInt &) to fltSemantics. Each semantics can specify how to convert between APFloat and APInt. No more switch case statements in IEEEFloat::bitcastToAPInt() etc.
  • Longer term: Turn fltSemantics into a public class that can be used to define custom floating-point types in downstream projects (without having to modify LLVM).

Any thoughts?

@durga4github
Copy link
Contributor

Hi @matthias-springer ,

Can we split this into at least two separate PRs?

One for the first two items in the commit message.
And one (or two) PRs for the rest of the changes.

Comment on lines 250 to 252
// TODO: Implement all operations in semPPCDoubleDouble, and delete these
// semantics.
S_PPCDoubleDoubleLegacy,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it seems like this was intentionally not added here as a publicly visible kind?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like S_PPCDoubleDoubleLegacy was meant to be removed, but nothing has happened in over 1.5 years. Probably even longer because the last change was just a refactoring.

I think S_PPCDoubleDoubleLegacy should be added here to make sure we have a consistent code base. (Unless somebody volunteers to finish the PPCDoubleDoubleLegacy removal.)

I am trying to decouple APFloat and the floating-point semantics and special cases like these make that difficult.

@matthias-springer matthias-springer force-pushed the users/matthias-springer/missing_semantics_enum branch from 35848f5 to ff1ba48 Compare December 4, 2024 18:40
@matthias-springer matthias-springer merged commit f50ce31 into main Dec 4, 2024
8 checks passed
@matthias-springer matthias-springer deleted the users/matthias-springer/missing_semantics_enum branch December 4, 2024 22:59
@kazutakahirata
Copy link
Contributor

@matthias-springer I've checked in 32b821c to fix a warning for now. Should S_PPCDoubleDoubleLegacy be treated the same way as S_PPCDoubleDouble?

@matthias-springer
Copy link
Member Author

Thanks for the fix! Given that S_PPCDoubleDoubleLegacy did not previously exist, I think your fix (llvm_unreachable) is correct.

@kazutakahirata
Copy link
Contributor

Thank you for the confirmation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category llvm:adt llvm:support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants