@@ -1462,6 +1462,10 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE constexpr auto signed_underflow_mul_msg() noexcep
14621462 return " Underflow detected in i128 multiplication" ;
14631463 }
14641464}
1465+
1466+ // clang lowers signed __builtin_mul_overflow on __int128 to __muloti4 (compiler-rt
1467+ // only), which is missing when linking libgcc on clang-13. Limit the fast path to
1468+ // GCC and clang >= 14; everything else uses signed_no_intrin_mul for int128.
14651469#if BOOST_SAFE_NUMBERS_HAS_BUILTIN(__builtin_mul_overflow) && defined(BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_INT128) && (!defined(__clang__) || __clang_major__ >= 14)
14661470# define BOOST_SAFE_NUMBERS_HAS_INT128_SIGNED_INTRIN_MUL
14671471#endif
@@ -1786,8 +1790,9 @@ struct signed_mul_helper
17861790
17871791 #if BOOST_SAFE_NUMBERS_HAS_BUILTIN(__builtin_mul_overflow) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X64_INTRIN) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X86_INTRIN)
17881792
1789- // We have a 128-bit intrin path, but only with __builtin_mul_overflow
1790- #if defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X64_INTRIN) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X86_INTRIN) || !defined(BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_INT128)
1793+ // Route int128 through the intrin path only where the signed 128-bit
1794+ // fast path links (GCC, clang >= 14); elsewhere it uses no_intrin.
1795+ #if !defined(BOOST_SAFE_NUMBERS_HAS_INT128_SIGNED_INTRIN_MUL)
17911796 if constexpr (!std::is_same_v<BasisType, int128::int128_t >)
17921797 #endif
17931798 {
@@ -1836,8 +1841,9 @@ struct signed_mul_helper<overflow_policy::overflow_tuple, BasisType>
18361841
18371842 #if BOOST_SAFE_NUMBERS_HAS_BUILTIN(__builtin_mul_overflow) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X64_INTRIN) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X86_INTRIN)
18381843
1839- // We have a 128-bit intrin path, but only with __builtin_mul_overflow
1840- #if defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X64_INTRIN) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X86_INTRIN) || !defined(BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_INT128)
1844+ // Route int128 through the intrin path only where the signed 128-bit
1845+ // fast path links (GCC, clang >= 14); elsewhere it uses no_intrin.
1846+ #if !defined(BOOST_SAFE_NUMBERS_HAS_INT128_SIGNED_INTRIN_MUL)
18411847 if constexpr (!std::is_same_v<BasisType, int128::int128_t >)
18421848 #endif
18431849 {
@@ -1876,8 +1882,9 @@ struct signed_mul_helper<overflow_policy::checked, BasisType>
18761882
18771883 #if BOOST_SAFE_NUMBERS_HAS_BUILTIN(__builtin_mul_overflow) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X64_INTRIN) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X86_INTRIN)
18781884
1879- // We have a 128-bit intrin path, but only with __builtin_mul_overflow
1880- #if defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X64_INTRIN) || defined(BOOST_SAFENUMBERS_HAS_WINDOWS_X86_INTRIN) || !defined(BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_INT128)
1885+ // Route int128 through the intrin path only where the signed 128-bit
1886+ // fast path links (GCC, clang >= 14); elsewhere it uses no_intrin.
1887+ #if !defined(BOOST_SAFE_NUMBERS_HAS_INT128_SIGNED_INTRIN_MUL)
18811888 if constexpr (!std::is_same_v<BasisType, int128::int128_t >)
18821889 #endif
18831890 {
0 commit comments