diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h index 8ec30396ffdb46..ae367994706c0f 100644 --- a/libc/src/__support/math_extras.h +++ b/libc/src/__support/math_extras.h @@ -56,11 +56,9 @@ add_with_carry_const(T a, T b, T carry_in) { return {sum, carry_out}; } -// This version is not always valid for constepxr because it's overriden below -// if builtins are available. template -LIBC_INLINE cpp::enable_if_t && cpp::is_unsigned_v, - SumCarry> +LIBC_INLINE constexpr cpp::enable_if_t< + cpp::is_integral_v && cpp::is_unsigned_v, SumCarry> add_with_carry(T a, T b, T carry_in) { return add_with_carry_const(a, b, carry_in); } @@ -69,48 +67,68 @@ add_with_carry(T a, T b, T carry_in) { // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins template <> -LIBC_INLINE SumCarry +LIBC_INLINE constexpr SumCarry add_with_carry(unsigned char a, unsigned char b, unsigned char carry_in) { - SumCarry result{0, 0}; - result.sum = __builtin_addcb(a, b, carry_in, &result.carry); - return result; + if (__builtin_is_constant_evaluated()) { + return add_with_carry_const(a, b, carry_in); + } else { + SumCarry result{0, 0}; + result.sum = __builtin_addcb(a, b, carry_in, &result.carry); + return result; + } } template <> -LIBC_INLINE SumCarry +LIBC_INLINE constexpr SumCarry add_with_carry(unsigned short a, unsigned short b, unsigned short carry_in) { - SumCarry result{0, 0}; - result.sum = __builtin_addcs(a, b, carry_in, &result.carry); - return result; + if (__builtin_is_constant_evaluated()) { + return add_with_carry_const(a, b, carry_in); + } else { + SumCarry result{0, 0}; + result.sum = __builtin_addcs(a, b, carry_in, &result.carry); + return result; + } } template <> -LIBC_INLINE SumCarry +LIBC_INLINE constexpr SumCarry add_with_carry(unsigned int a, unsigned int b, unsigned int carry_in) { - SumCarry result{0, 0}; - result.sum = __builtin_addc(a, b, carry_in, &result.carry); - return result; + if (__builtin_is_constant_evaluated()) { + return add_with_carry_const(a, b, carry_in); + } else { + SumCarry result{0, 0}; + result.sum = __builtin_addc(a, b, carry_in, &result.carry); + return result; + } } template <> -LIBC_INLINE SumCarry +LIBC_INLINE constexpr SumCarry add_with_carry(unsigned long a, unsigned long b, unsigned long carry_in) { - SumCarry result{0, 0}; - result.sum = __builtin_addcl(a, b, carry_in, &result.carry); - return result; + if (__builtin_is_constant_evaluated()) { + return add_with_carry_const(a, b, carry_in); + } else { + SumCarry result{0, 0}; + result.sum = __builtin_addcl(a, b, carry_in, &result.carry); + return result; + } } template <> -LIBC_INLINE SumCarry +LIBC_INLINE constexpr SumCarry add_with_carry(unsigned long long a, unsigned long long b, unsigned long long carry_in) { - SumCarry result{0, 0}; - result.sum = __builtin_addcll(a, b, carry_in, &result.carry); - return result; + if (__builtin_is_constant_evaluated()) { + return add_with_carry_const(a, b, carry_in); + } else { + SumCarry result{0, 0}; + result.sum = __builtin_addcll(a, b, carry_in, &result.carry); + return result; + } } #endif // LIBC_HAS_BUILTIN(__builtin_addc) @@ -135,8 +153,8 @@ sub_with_borrow_const(T a, T b, T borrow_in) { // This version is not always valid for constepxr because it's overriden below // if builtins are available. template -LIBC_INLINE cpp::enable_if_t && cpp::is_unsigned_v, - DiffBorrow> +LIBC_INLINE constexpr cpp::enable_if_t< + cpp::is_integral_v && cpp::is_unsigned_v, DiffBorrow> sub_with_borrow(T a, T b, T borrow_in) { return sub_with_borrow_const(a, b, borrow_in); } @@ -145,48 +163,68 @@ sub_with_borrow(T a, T b, T borrow_in) { // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins template <> -LIBC_INLINE DiffBorrow +LIBC_INLINE constexpr DiffBorrow sub_with_borrow(unsigned char a, unsigned char b, unsigned char borrow_in) { - DiffBorrow result{0, 0}; - result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow); - return result; + if (__builtin_is_constant_evaluated()) { + return sub_with_borrow_const(a, b, borrow_in); + } else { + DiffBorrow result{0, 0}; + result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow); + return result; + } } template <> -LIBC_INLINE DiffBorrow +LIBC_INLINE constexpr DiffBorrow sub_with_borrow(unsigned short a, unsigned short b, unsigned short borrow_in) { - DiffBorrow result{0, 0}; - result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow); - return result; + if (__builtin_is_constant_evaluated()) { + return sub_with_borrow_const(a, b, borrow_in); + } else { + DiffBorrow result{0, 0}; + result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow); + return result; + } } template <> -LIBC_INLINE DiffBorrow +LIBC_INLINE constexpr DiffBorrow sub_with_borrow(unsigned int a, unsigned int b, unsigned int borrow_in) { - DiffBorrow result{0, 0}; - result.diff = __builtin_subc(a, b, borrow_in, &result.borrow); - return result; + if (__builtin_is_constant_evaluated()) { + return sub_with_borrow_const(a, b, borrow_in); + } else { + DiffBorrow result{0, 0}; + result.diff = __builtin_subc(a, b, borrow_in, &result.borrow); + return result; + } } template <> -LIBC_INLINE DiffBorrow +LIBC_INLINE constexpr DiffBorrow sub_with_borrow(unsigned long a, unsigned long b, unsigned long borrow_in) { - DiffBorrow result{0, 0}; - result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow); - return result; + if (__builtin_is_constant_evaluated()) { + return sub_with_borrow_const(a, b, borrow_in); + } else { + DiffBorrow result{0, 0}; + result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow); + return result; + } } template <> -LIBC_INLINE DiffBorrow +LIBC_INLINE constexpr DiffBorrow sub_with_borrow(unsigned long long a, unsigned long long b, unsigned long long borrow_in) { - DiffBorrow result{0, 0}; - result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow); - return result; + if (__builtin_is_constant_evaluated()) { + return sub_with_borrow_const(a, b, borrow_in); + } else { + DiffBorrow result{0, 0}; + result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow); + return result; + } } #endif // LIBC_HAS_BUILTIN(__builtin_subc)