[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