-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] Make add_with_carry and sub_with_borrow constexpr. #81898
Conversation
@llvm/pr-subscribers-libc Author: None (lntue) ChangesFull diff: https://github.com/llvm/llvm-project/pull/81898.diff 1 Files Affected:
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)
|
SumCarry<unsigned char> result{0, 0}; | ||
result.sum = __builtin_addcb(a, b, carry_in, &result.carry); | ||
return result; | ||
if (__builtin_is_constant_evaluated()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this builtin need a guard to check if it's available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've checked on godbolt, and seems like it works fine on clang 9.0+ and gcc 11+ in all x86-64, arm32, and riscv-32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat, TIL about __builtin_is_constant_evaluated
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
No description provided.