[libc-commits] [libc] [libc] Make add_with_carry and sub_with_borrow constexpr. (PR #81898)
via libc-commits
libc-commits at lists.llvm.org
Thu Feb 15 10:43:24 PST 2024
https://github.com/lntue created https://github.com/llvm/llvm-project/pull/81898
None
>From f62140925fb5dcd114ba1f23e50fecba569ec171 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 15 Feb 2024 18:41:29 +0000
Subject: [PATCH] [libc] Make add_with_carry and sub_with_borrow constexpr.
---
libc/src/__support/math_extras.h | 130 ++++++++++++++++++++-----------
1 file changed, 84 insertions(+), 46 deletions(-)
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 <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T>,
- SumCarry<T>>
+LIBC_INLINE constexpr cpp::enable_if_t<
+ cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, SumCarry<T>>
add_with_carry(T a, T b, T carry_in) {
return add_with_carry_const<T>(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<unsigned char>
+LIBC_INLINE constexpr SumCarry<unsigned char>
add_with_carry<unsigned char>(unsigned char a, unsigned char b,
unsigned char carry_in) {
- SumCarry<unsigned char> 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<unsigned char>(a, b, carry_in);
+ } else {
+ SumCarry<unsigned char> result{0, 0};
+ result.sum = __builtin_addcb(a, b, carry_in, &result.carry);
+ return result;
+ }
}
template <>
-LIBC_INLINE SumCarry<unsigned short>
+LIBC_INLINE constexpr SumCarry<unsigned short>
add_with_carry<unsigned short>(unsigned short a, unsigned short b,
unsigned short carry_in) {
- SumCarry<unsigned short> 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<unsigned short>(a, b, carry_in);
+ } else {
+ SumCarry<unsigned short> result{0, 0};
+ result.sum = __builtin_addcs(a, b, carry_in, &result.carry);
+ return result;
+ }
}
template <>
-LIBC_INLINE SumCarry<unsigned int>
+LIBC_INLINE constexpr SumCarry<unsigned int>
add_with_carry<unsigned int>(unsigned int a, unsigned int b,
unsigned int carry_in) {
- SumCarry<unsigned int> 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<unsigned int>(a, b, carry_in);
+ } else {
+ SumCarry<unsigned int> result{0, 0};
+ result.sum = __builtin_addc(a, b, carry_in, &result.carry);
+ return result;
+ }
}
template <>
-LIBC_INLINE SumCarry<unsigned long>
+LIBC_INLINE constexpr SumCarry<unsigned long>
add_with_carry<unsigned long>(unsigned long a, unsigned long b,
unsigned long carry_in) {
- SumCarry<unsigned long> 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<unsigned long>(a, b, carry_in);
+ } else {
+ SumCarry<unsigned long> result{0, 0};
+ result.sum = __builtin_addcl(a, b, carry_in, &result.carry);
+ return result;
+ }
}
template <>
-LIBC_INLINE SumCarry<unsigned long long>
+LIBC_INLINE constexpr SumCarry<unsigned long long>
add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b,
unsigned long long carry_in) {
- SumCarry<unsigned long long> 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<unsigned long long>(a, b, carry_in);
+ } else {
+ SumCarry<unsigned long long> 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 <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T>,
- DiffBorrow<T>>
+LIBC_INLINE constexpr cpp::enable_if_t<
+ cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, DiffBorrow<T>>
sub_with_borrow(T a, T b, T borrow_in) {
return sub_with_borrow_const<T>(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<unsigned char>
+LIBC_INLINE constexpr DiffBorrow<unsigned char>
sub_with_borrow<unsigned char>(unsigned char a, unsigned char b,
unsigned char borrow_in) {
- DiffBorrow<unsigned char> 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<unsigned char>(a, b, borrow_in);
+ } else {
+ DiffBorrow<unsigned char> result{0, 0};
+ result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow);
+ return result;
+ }
}
template <>
-LIBC_INLINE DiffBorrow<unsigned short>
+LIBC_INLINE constexpr DiffBorrow<unsigned short>
sub_with_borrow<unsigned short>(unsigned short a, unsigned short b,
unsigned short borrow_in) {
- DiffBorrow<unsigned short> 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<unsigned short>(a, b, borrow_in);
+ } else {
+ DiffBorrow<unsigned short> result{0, 0};
+ result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow);
+ return result;
+ }
}
template <>
-LIBC_INLINE DiffBorrow<unsigned int>
+LIBC_INLINE constexpr DiffBorrow<unsigned int>
sub_with_borrow<unsigned int>(unsigned int a, unsigned int b,
unsigned int borrow_in) {
- DiffBorrow<unsigned int> 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<unsigned int>(a, b, borrow_in);
+ } else {
+ DiffBorrow<unsigned int> result{0, 0};
+ result.diff = __builtin_subc(a, b, borrow_in, &result.borrow);
+ return result;
+ }
}
template <>
-LIBC_INLINE DiffBorrow<unsigned long>
+LIBC_INLINE constexpr DiffBorrow<unsigned long>
sub_with_borrow<unsigned long>(unsigned long a, unsigned long b,
unsigned long borrow_in) {
- DiffBorrow<unsigned long> 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<unsigned long>(a, b, borrow_in);
+ } else {
+ DiffBorrow<unsigned long> result{0, 0};
+ result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow);
+ return result;
+ }
}
template <>
-LIBC_INLINE DiffBorrow<unsigned long long>
+LIBC_INLINE constexpr DiffBorrow<unsigned long long>
sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b,
unsigned long long borrow_in) {
- DiffBorrow<unsigned long long> 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<unsigned long long>(a, b, borrow_in);
+ } else {
+ DiffBorrow<unsigned long long> result{0, 0};
+ result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow);
+ return result;
+ }
}
#endif // LIBC_HAS_BUILTIN(__builtin_subc)
More information about the libc-commits
mailing list