Skip to content

Commit 495c57f

Browse files
authored
[libc] Make add_with_carry and sub_with_borrow constexpr. (llvm#81898)
1 parent 04381c1 commit 495c57f

File tree

1 file changed

+84
-46
lines changed

1 file changed

+84
-46
lines changed

libc/src/__support/math_extras.h

Lines changed: 84 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,9 @@ add_with_carry_const(T a, T b, T carry_in) {
5656
return {sum, carry_out};
5757
}
5858

59-
// This version is not always valid for constepxr because it's overriden below
60-
// if builtins are available.
6159
template <typename T>
62-
LIBC_INLINE cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T>,
63-
SumCarry<T>>
60+
LIBC_INLINE constexpr cpp::enable_if_t<
61+
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, SumCarry<T>>
6462
add_with_carry(T a, T b, T carry_in) {
6563
return add_with_carry_const<T>(a, b, carry_in);
6664
}
@@ -69,48 +67,68 @@ add_with_carry(T a, T b, T carry_in) {
6967
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
7068

7169
template <>
72-
LIBC_INLINE SumCarry<unsigned char>
70+
LIBC_INLINE constexpr SumCarry<unsigned char>
7371
add_with_carry<unsigned char>(unsigned char a, unsigned char b,
7472
unsigned char carry_in) {
75-
SumCarry<unsigned char> result{0, 0};
76-
result.sum = __builtin_addcb(a, b, carry_in, &result.carry);
77-
return result;
73+
if (__builtin_is_constant_evaluated()) {
74+
return add_with_carry_const<unsigned char>(a, b, carry_in);
75+
} else {
76+
SumCarry<unsigned char> result{0, 0};
77+
result.sum = __builtin_addcb(a, b, carry_in, &result.carry);
78+
return result;
79+
}
7880
}
7981

8082
template <>
81-
LIBC_INLINE SumCarry<unsigned short>
83+
LIBC_INLINE constexpr SumCarry<unsigned short>
8284
add_with_carry<unsigned short>(unsigned short a, unsigned short b,
8385
unsigned short carry_in) {
84-
SumCarry<unsigned short> result{0, 0};
85-
result.sum = __builtin_addcs(a, b, carry_in, &result.carry);
86-
return result;
86+
if (__builtin_is_constant_evaluated()) {
87+
return add_with_carry_const<unsigned short>(a, b, carry_in);
88+
} else {
89+
SumCarry<unsigned short> result{0, 0};
90+
result.sum = __builtin_addcs(a, b, carry_in, &result.carry);
91+
return result;
92+
}
8793
}
8894

8995
template <>
90-
LIBC_INLINE SumCarry<unsigned int>
96+
LIBC_INLINE constexpr SumCarry<unsigned int>
9197
add_with_carry<unsigned int>(unsigned int a, unsigned int b,
9298
unsigned int carry_in) {
93-
SumCarry<unsigned int> result{0, 0};
94-
result.sum = __builtin_addc(a, b, carry_in, &result.carry);
95-
return result;
99+
if (__builtin_is_constant_evaluated()) {
100+
return add_with_carry_const<unsigned int>(a, b, carry_in);
101+
} else {
102+
SumCarry<unsigned int> result{0, 0};
103+
result.sum = __builtin_addc(a, b, carry_in, &result.carry);
104+
return result;
105+
}
96106
}
97107

98108
template <>
99-
LIBC_INLINE SumCarry<unsigned long>
109+
LIBC_INLINE constexpr SumCarry<unsigned long>
100110
add_with_carry<unsigned long>(unsigned long a, unsigned long b,
101111
unsigned long carry_in) {
102-
SumCarry<unsigned long> result{0, 0};
103-
result.sum = __builtin_addcl(a, b, carry_in, &result.carry);
104-
return result;
112+
if (__builtin_is_constant_evaluated()) {
113+
return add_with_carry_const<unsigned long>(a, b, carry_in);
114+
} else {
115+
SumCarry<unsigned long> result{0, 0};
116+
result.sum = __builtin_addcl(a, b, carry_in, &result.carry);
117+
return result;
118+
}
105119
}
106120

107121
template <>
108-
LIBC_INLINE SumCarry<unsigned long long>
122+
LIBC_INLINE constexpr SumCarry<unsigned long long>
109123
add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b,
110124
unsigned long long carry_in) {
111-
SumCarry<unsigned long long> result{0, 0};
112-
result.sum = __builtin_addcll(a, b, carry_in, &result.carry);
113-
return result;
125+
if (__builtin_is_constant_evaluated()) {
126+
return add_with_carry_const<unsigned long long>(a, b, carry_in);
127+
} else {
128+
SumCarry<unsigned long long> result{0, 0};
129+
result.sum = __builtin_addcll(a, b, carry_in, &result.carry);
130+
return result;
131+
}
114132
}
115133

116134
#endif // LIBC_HAS_BUILTIN(__builtin_addc)
@@ -135,8 +153,8 @@ sub_with_borrow_const(T a, T b, T borrow_in) {
135153
// This version is not always valid for constepxr because it's overriden below
136154
// if builtins are available.
137155
template <typename T>
138-
LIBC_INLINE cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T>,
139-
DiffBorrow<T>>
156+
LIBC_INLINE constexpr cpp::enable_if_t<
157+
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, DiffBorrow<T>>
140158
sub_with_borrow(T a, T b, T borrow_in) {
141159
return sub_with_borrow_const<T>(a, b, borrow_in);
142160
}
@@ -145,48 +163,68 @@ sub_with_borrow(T a, T b, T borrow_in) {
145163
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
146164

147165
template <>
148-
LIBC_INLINE DiffBorrow<unsigned char>
166+
LIBC_INLINE constexpr DiffBorrow<unsigned char>
149167
sub_with_borrow<unsigned char>(unsigned char a, unsigned char b,
150168
unsigned char borrow_in) {
151-
DiffBorrow<unsigned char> result{0, 0};
152-
result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow);
153-
return result;
169+
if (__builtin_is_constant_evaluated()) {
170+
return sub_with_borrow_const<unsigned char>(a, b, borrow_in);
171+
} else {
172+
DiffBorrow<unsigned char> result{0, 0};
173+
result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow);
174+
return result;
175+
}
154176
}
155177

156178
template <>
157-
LIBC_INLINE DiffBorrow<unsigned short>
179+
LIBC_INLINE constexpr DiffBorrow<unsigned short>
158180
sub_with_borrow<unsigned short>(unsigned short a, unsigned short b,
159181
unsigned short borrow_in) {
160-
DiffBorrow<unsigned short> result{0, 0};
161-
result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow);
162-
return result;
182+
if (__builtin_is_constant_evaluated()) {
183+
return sub_with_borrow_const<unsigned short>(a, b, borrow_in);
184+
} else {
185+
DiffBorrow<unsigned short> result{0, 0};
186+
result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow);
187+
return result;
188+
}
163189
}
164190

165191
template <>
166-
LIBC_INLINE DiffBorrow<unsigned int>
192+
LIBC_INLINE constexpr DiffBorrow<unsigned int>
167193
sub_with_borrow<unsigned int>(unsigned int a, unsigned int b,
168194
unsigned int borrow_in) {
169-
DiffBorrow<unsigned int> result{0, 0};
170-
result.diff = __builtin_subc(a, b, borrow_in, &result.borrow);
171-
return result;
195+
if (__builtin_is_constant_evaluated()) {
196+
return sub_with_borrow_const<unsigned int>(a, b, borrow_in);
197+
} else {
198+
DiffBorrow<unsigned int> result{0, 0};
199+
result.diff = __builtin_subc(a, b, borrow_in, &result.borrow);
200+
return result;
201+
}
172202
}
173203

174204
template <>
175-
LIBC_INLINE DiffBorrow<unsigned long>
205+
LIBC_INLINE constexpr DiffBorrow<unsigned long>
176206
sub_with_borrow<unsigned long>(unsigned long a, unsigned long b,
177207
unsigned long borrow_in) {
178-
DiffBorrow<unsigned long> result{0, 0};
179-
result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow);
180-
return result;
208+
if (__builtin_is_constant_evaluated()) {
209+
return sub_with_borrow_const<unsigned long>(a, b, borrow_in);
210+
} else {
211+
DiffBorrow<unsigned long> result{0, 0};
212+
result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow);
213+
return result;
214+
}
181215
}
182216

183217
template <>
184-
LIBC_INLINE DiffBorrow<unsigned long long>
218+
LIBC_INLINE constexpr DiffBorrow<unsigned long long>
185219
sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b,
186220
unsigned long long borrow_in) {
187-
DiffBorrow<unsigned long long> result{0, 0};
188-
result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow);
189-
return result;
221+
if (__builtin_is_constant_evaluated()) {
222+
return sub_with_borrow_const<unsigned long long>(a, b, borrow_in);
223+
} else {
224+
DiffBorrow<unsigned long long> result{0, 0};
225+
result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow);
226+
return result;
227+
}
190228
}
191229

192230
#endif // LIBC_HAS_BUILTIN(__builtin_subc)

0 commit comments

Comments
 (0)