diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h index 49fb11971104b3..12a69228d36c7b 100644 --- a/libc/src/__support/FPUtil/dyadic_float.h +++ b/libc/src/__support/FPUtil/dyadic_float.h @@ -122,7 +122,8 @@ template struct DyadicFloat { int exp_lo = exp_hi - static_cast(PRECISION) - 1; - MantissaType m_hi(mantissa >> shift); + MantissaType m_hi = + shift >= MantissaType::BITS ? MantissaType(0) : mantissa >> shift; T d_hi = FPBits::create_value( sign, exp_hi, @@ -130,7 +131,8 @@ template struct DyadicFloat { IMPLICIT_MASK) .get_val(); - MantissaType round_mask = MantissaType(1) << (shift - 1); + MantissaType round_mask = + shift > MantissaType::BITS ? 0 : MantissaType(1) << (shift - 1); MantissaType sticky_mask = round_mask - MantissaType(1); bool round_bit = !(mantissa & round_mask).is_zero(); diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h index c1e55ceef21113..f722a81d357d4f 100644 --- a/libc/src/__support/big_int.h +++ b/libc/src/__support/big_int.h @@ -249,18 +249,14 @@ LIBC_INLINE constexpr bool is_negative(cpp::array &array) { enum Direction { LEFT, RIGHT }; // A bitwise shift on an array of elements. -// TODO: Make the result UB when 'offset' is greater or equal to the number of -// bits in 'array'. This will allow for better code performance. +// 'offset' must be less than TOTAL_BITS (i.e., sizeof(word) * CHAR_BIT * N) +// otherwise the behavior is undefined. template LIBC_INLINE constexpr cpp::array shift(cpp::array array, size_t offset) { static_assert(direction == LEFT || direction == RIGHT); constexpr size_t WORD_BITS = cpp::numeric_limits::digits; constexpr size_t TOTAL_BITS = N * WORD_BITS; - if (LIBC_UNLIKELY(offset == 0)) - return array; - if (LIBC_UNLIKELY(offset >= TOTAL_BITS)) - return {}; #ifdef LIBC_TYPES_HAS_INT128 if constexpr (TOTAL_BITS == 128) { using type = cpp::conditional_t; @@ -272,6 +268,8 @@ LIBC_INLINE constexpr cpp::array shift(cpp::array array, return cpp::bit_cast>(tmp); } #endif + if (LIBC_UNLIKELY(offset == 0)) + return array; const bool is_neg = is_signed && is_negative(array); constexpr auto at = [](size_t index) -> int { // reverse iteration when direction == LEFT. diff --git a/libc/test/src/__support/big_int_test.cpp b/libc/test/src/__support/big_int_test.cpp index fadec0cc313b16..1c4f0ac29171fa 100644 --- a/libc/test/src/__support/big_int_test.cpp +++ b/libc/test/src/__support/big_int_test.cpp @@ -192,7 +192,7 @@ TYPED_TEST(LlvmLibcUIntClassTest, Masks, Types) { TYPED_TEST(LlvmLibcUIntClassTest, CountBits, Types) { if constexpr (!T::SIGNED) { - for (size_t i = 0; i <= T::BITS; ++i) { + for (size_t i = 0; i < T::BITS; ++i) { const auto l_one = T::all_ones() << i; // 0b111...000 const auto r_one = T::all_ones() >> i; // 0b000...111 const int zeros = i; @@ -559,10 +559,6 @@ TEST(LlvmLibcUIntClassTest, ShiftLeftTests) { LL_UInt128 result5({0, 0x2468ace000000000}); EXPECT_EQ((val2 << 100), result5); - LL_UInt128 result6({0, 0}); - EXPECT_EQ((val2 << 128), result6); - EXPECT_EQ((val2 << 256), result6); - LL_UInt192 val3({1, 0, 0}); LL_UInt192 result7({0, 1, 0}); EXPECT_EQ((val3 << 64), result7); @@ -589,10 +585,6 @@ TEST(LlvmLibcUIntClassTest, ShiftRightTests) { LL_UInt128 result5({0x0000000001234567, 0}); EXPECT_EQ((val2 >> 100), result5); - LL_UInt128 result6({0, 0}); - EXPECT_EQ((val2 >> 128), result6); - EXPECT_EQ((val2 >> 256), result6); - LL_UInt128 v1({0x1111222233334444, 0xaaaabbbbccccdddd}); LL_UInt128 r1({0xaaaabbbbccccdddd, 0}); EXPECT_EQ((v1 >> 64), r1);