[libc-commits] [libc] d1e261e - [libc] Fix fxdivi tests on 32-bit targets (#223675)

via libc-commits libc-commits at lists.llvm.org
Wed Sep 16 01:58:49 PDT 2026


Author: Victor Campos
Date: 2026-09-16T09:58:43+01:00
New Revision: d1e261e574e9612fe3f4056730809617323f1758

URL: https://github.com/llvm/llvm-project/commit/d1e261e574e9612fe3f4056730809617323f1758
DIFF: https://github.com/llvm/llvm-project/commit/d1e261e574e9612fe3f4056730809617323f1758.diff

LOG: [libc] Fix fxdivi tests on 32-bit targets (#223675)

Guard saturation operands against overflow and correct boundary
expectations for the range and precision of 32-bit long.

Fixes issue introduced in a969579a9129891bccb63fcc69e76d74b299f322.

Assisted-by: Codex. Entirely done by the AI and reviewed by me.

Added: 
    

Modified: 
    libc/test/src/stdfix/FxDiviTest.h

Removed: 
    


################################################################################
diff  --git a/libc/test/src/stdfix/FxDiviTest.h b/libc/test/src/stdfix/FxDiviTest.h
index 3ee90d71c0542..4ff14c41b621d 100644
--- a/libc/test/src/stdfix/FxDiviTest.h
+++ b/libc/test/src/stdfix/FxDiviTest.h
@@ -84,6 +84,7 @@ class FxDiviTest : public LIBC_NAMESPACE::testing::Test {
   }
 
   void testEdgeCases(FxDiviFunc func) {
+    constexpr int int_digits = cpp::numeric_limits<IntType>::digits;
     constexpr IntType int_max = cpp::numeric_limits<IntType>::max();
 
     EXPECT_EQ(func(0, 10), fx_zero);
@@ -91,7 +92,7 @@ class FxDiviTest : public LIBC_NAMESPACE::testing::Test {
       EXPECT_EQ(func(0, -10), fx_zero);
     }
 
-    if constexpr (is_signed && (F < cpp::numeric_limits<IntType>::digits)) {
+    if constexpr (is_signed && (F < int_digits)) {
       constexpr IntType edge = static_cast<IntType>(1) << F;
       EXPECT_EQ(func(-edge, edge), static_cast<FXType>(-1));
       if constexpr (has_integral) {
@@ -105,16 +106,24 @@ class FxDiviTest : public LIBC_NAMESPACE::testing::Test {
       EXPECT_EQ(func(int_max, int_max), static_cast<FXType>(1));
       EXPECT_TRUE(abs_
diff (func(int_max - 1, int_max),
                            static_cast<FXType>(1) - epsilon) <= epsilon);
-      EXPECT_EQ(func(int_max, 1), fx_max);
+      // Integer extrema need not overflow the fixed-point result type.
+      if constexpr (int_digits <= FXRep::INTEGRAL_LEN)
+        EXPECT_EQ(func(int_max, 1), static_cast<FXType>(int_max));
+      else
+        EXPECT_EQ(func(int_max, 1), fx_max);
     } else {
       EXPECT_EQ(func(int_max, int_max), fx_max);
-      EXPECT_EQ(func(int_max - 1, int_max), fx_max);
+      // When the integer and fraction precisions match, this quotient can
+      // round to one ulp below fx_max.
+      if constexpr (int_digits == F)
+        EXPECT_TRUE(abs_
diff (func(int_max - 1, int_max), fx_max) <= epsilon);
+      else
+        EXPECT_EQ(func(int_max - 1, int_max), fx_max);
       EXPECT_EQ(func(27, 23), fx_max);
     }
 
-    // Cannot EXPECT_EQ even though int_max is a power of 2 because rounding
-    // direction for magnitudes smaller than the representable precision is
-    // implementation defined. The result must be within 1 ulp.
+    // Rounding direction for magnitudes smaller than the representable
+    // precision is implementation defined. The result must be within 1 ulp.
     EXPECT_TRUE(abs_
diff (func(1, int_max), fx_zero) <= epsilon);
 
     if constexpr (is_signed) {
@@ -129,15 +138,25 @@ class FxDiviTest : public LIBC_NAMESPACE::testing::Test {
         EXPECT_EQ(func(int_min, int_min), fx_max);
       }
 
-      EXPECT_EQ(func(int_min, 1), fx_min);
+      if constexpr (int_digits <= FXRep::INTEGRAL_LEN) {
+        EXPECT_EQ(func(int_min, 1), static_cast<FXType>(int_min));
+        EXPECT_EQ(func(int_max, -1), -static_cast<FXType>(int_max));
+      } else {
+        EXPECT_EQ(func(int_min, 1), fx_min);
+        EXPECT_EQ(func(int_max, -1), fx_min);
+      }
 
       // Cannot EXPECT_EQ even though int_min is a power of 2 because rounding
       // direction for magnitudes smaller than the representable precision is
       // implementation defined. The result must be within 1 ulp.
       EXPECT_TRUE(abs_
diff (func(1, int_min), fx_zero) <= epsilon);
 
-      EXPECT_EQ(func(int_min, -1), fx_max);
-      EXPECT_EQ(func(int_max, -1), fx_min);
+      // The positive magnitude of int_min needs one more integral bit than
+      // int_max. Convert before negating to avoid integer overflow.
+      if constexpr (int_digits < FXRep::INTEGRAL_LEN)
+        EXPECT_EQ(func(int_min, -1), -static_cast<FXType>(int_min));
+      else
+        EXPECT_EQ(func(int_min, -1), fx_max);
     }
 
     if constexpr (has_integral) {
@@ -166,13 +185,14 @@ class FxDiviTest : public LIBC_NAMESPACE::testing::Test {
       }
     }
 
-    if constexpr (has_integral) {
-      constexpr IntType over_max =
-          static_cast<IntType>(6) *
-          (static_cast<IntType>(1) << FXRep::INTEGRAL_LEN);
-      EXPECT_EQ(func(over_max, 3), fx_max);
+    // Construct saturation operands only when they fit in IntType.
+    if constexpr (has_integral && FXRep::INTEGRAL_LEN < int_digits) {
       constexpr IntType at_max = static_cast<IntType>(1) << FXRep::INTEGRAL_LEN;
       EXPECT_EQ(func(at_max, 1), fx_max);
+      if constexpr (at_max <= int_max / 6) {
+        constexpr IntType over_max = static_cast<IntType>(6) * at_max;
+        EXPECT_EQ(func(over_max, 3), fx_max);
+      }
     }
   }
 
@@ -196,7 +216,7 @@ class FxDiviTest : public LIBC_NAMESPACE::testing::Test {
     }
   }
 
-  void testInvalidNumbers(FxDiviFunc func) {
+  void testInvalidNumbers([[maybe_unused]] FxDiviFunc func) {
     EXPECT_DEATH([func] { func(1, 0); }, WITH_SIGNAL(-1));
     if constexpr (is_signed) {
       EXPECT_DEATH([func] { func(-1, 0); }, WITH_SIGNAL(-1));


        


More information about the libc-commits mailing list