Skip to content

Commit

Permalink
Merge pull request #725 from cppalliance/128
Browse files Browse the repository at this point in the history
Remove u128 x64 intrinsic pessimzations
  • Loading branch information
mborland committed Sep 19, 2024
2 parents 693907f + c995e23 commit 7fe2e8f
Showing 1 changed file with 22 additions and 68 deletions.
90 changes: 22 additions & 68 deletions include/boost/decimal/detail/emulated128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,31 +757,15 @@ constexpr auto uint128::operator+=(std::uint64_t n) noexcept -> uint128&

constexpr auto operator+(uint128 lhs, uint128 rhs) noexcept -> uint128
{
#if (defined(BOOST_DECIMAL_HAS_X64_INTRINSICS) || defined(BOOST_DECIMAL_HAS_MSVC_64BIT_INTRINSICS)) && !defined(BOOST_DECIMAL_NO_CONSTEVAL_DETECTION)
if (!BOOST_DECIMAL_IS_CONSTANT_EVALUATED(lhs.low))
{
// Branchless version can be executed on x64 machines when available
unsigned long long low {};
unsigned long long high {};

const auto carry {BOOST_DECIMAL_ADD_CARRY(0, lhs.low, rhs.low, &low)};
BOOST_DECIMAL_ADD_CARRY(carry, lhs.high, rhs.high, &high);
uint128 temp {lhs.high + rhs.high, lhs.low + rhs.low};

return uint128{high, low};
}
else
#endif
// Need to carry a bit into rhs
if (temp.low < lhs.low)
{
uint128 temp {lhs.high + rhs.high, lhs.low + rhs.low};

// Need to carry a bit into rhs
if (temp.low < lhs.low)
{
++temp.high;
}

return temp;
++temp.high;
}

return temp;
}

constexpr auto uint128::operator+=(uint128 v) noexcept -> uint128&
Expand All @@ -807,31 +791,15 @@ constexpr auto uint128::operator++(int) noexcept -> uint128

constexpr auto operator-(uint128 lhs, uint128 rhs) noexcept -> uint128
{
#if (defined(BOOST_DECIMAL_HAS_X64_INTRINSICS) || defined(BOOST_DECIMAL_HAS_MSVC_64BIT_INTRINSICS)) && !defined(BOOST_DECIMAL_NO_CONSTEVAL_DETECTION)
if (!BOOST_DECIMAL_IS_CONSTANT_EVALUATED(lhs.low))
{
// Branchless version can be executed on x64 machines when available
unsigned long long low {};
unsigned long long high {};

const auto carry {_subborrow_u64(0, lhs.low, rhs.low, &low)};
_subborrow_u64(carry, lhs.high, rhs.high, &high);
uint128 temp {lhs.high - rhs.high, lhs.low - rhs.low};

return uint128{high, low};
}
else
#endif
// Check for carry
if (lhs.low < rhs.low)
{
uint128 temp {lhs.high - rhs.high, lhs.low - rhs.low};

// Check for carry
if (lhs.low < rhs.low)
{
--temp.high;
}

return temp;
--temp.high;
}

return temp;
}

constexpr auto uint128::operator-=(uint128 v) noexcept -> uint128&
Expand Down Expand Up @@ -1328,35 +1296,21 @@ constexpr auto int128::operator>(int rhs) const noexcept -> bool

constexpr auto operator+(const int128& lhs, const int128& rhs) noexcept -> int128
{
#if (defined(BOOST_DECIMAL_HAS_X64_INTRINSICS) || defined(BOOST_DECIMAL_HAS_MSVC_64BIT_INTRINSICS)) && !defined(BOOST_DECIMAL_NO_CONSTEVAL_DETECTION)
if (!BOOST_DECIMAL_IS_CONSTANT_EVALUATED(lhs.low))
{
unsigned long long low {};
unsigned long long high {};

const auto carry {BOOST_DECIMAL_ADD_CARRY(0, lhs.low, rhs.low, &low)};
BOOST_DECIMAL_ADD_CARRY(carry, static_cast<std::uint64_t>(lhs.high), static_cast<std::uint64_t>(rhs.high), &high);

return {static_cast<std::int64_t>(high), low};
}
#endif
{
#ifdef BOOST_DECIMAL_HAS_INT128
#ifdef BOOST_DECIMAL_HAS_INT128

const auto lhs_full {(static_cast<__uint128_t>(lhs.high) << 64) | lhs.low};
const auto rhs_full {(static_cast<__uint128_t>(rhs.high) << 64) | rhs.low};
const auto result {lhs_full + rhs_full};
const auto lhs_full {(static_cast<__uint128_t>(lhs.high) << 64) | lhs.low};
const auto rhs_full {(static_cast<__uint128_t>(rhs.high) << 64) | rhs.low};
const auto result {lhs_full + rhs_full};

return {static_cast<std::int64_t>(result >> 64), static_cast<std::uint64_t>(result)};
return {static_cast<std::int64_t>(result >> 64), static_cast<std::uint64_t>(result)};

#else
#else

const auto new_low {lhs.low + rhs.low};
const auto new_high {lhs.high + rhs.high + static_cast<std::int64_t>(new_low < lhs.low)};
return int128{new_high, new_low};
const auto new_low {lhs.low + rhs.low};
const auto new_high {lhs.high + rhs.high + static_cast<std::int64_t>(new_low < lhs.low)};
return int128{new_high, new_low};

#endif
}
#endif
}

constexpr auto operator-(const int128& lhs, const int128& rhs) noexcept -> int128
Expand Down

0 comments on commit 7fe2e8f

Please sign in to comment.