Skip to content

Commit e205fc1

Browse files
committed
[libc] Add sub_with_borrow to builtin_wrapper.h
Add sub_with_borrow to builtin_wrapper.h to be used in UInt. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D138182
1 parent 420d0d3 commit e205fc1

File tree

7 files changed

+149
-46
lines changed

7 files changed

+149
-46
lines changed

libc/src/__support/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ add_header_library(
66
blockstore.h
77
)
88

9+
add_header_library(
10+
named_pair
11+
HDRS
12+
named_pair.h
13+
)
14+
915
add_header_library(
1016
builtin_wrappers
1117
HDRS
1218
builtin_wrappers.h
1319
DEPENDS
20+
.named_pair
1421
libc.src.__support.CPP.type_traits
1522
)
1623

@@ -111,6 +118,7 @@ add_header_library(
111118
HDRS
112119
number_pair.h
113120
DEPENDS
121+
.named_pair
114122
libc.src.__support.CPP.type_traits
115123
)
116124

libc/src/__support/UInt.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,22 +101,20 @@ template <size_t Bits> struct UInt {
101101
// property of unsigned integers:
102102
// x + (~x) = 2^(sizeof(x)) - 1.
103103
constexpr uint64_t add(const UInt<Bits> &x) {
104-
uint64_t carry_in = 0;
105-
uint64_t carry_out = 0;
104+
SumCarry<uint64_t> s{0, 0};
106105
for (size_t i = 0; i < WordCount; ++i) {
107-
val[i] = add_with_carry(val[i], x.val[i], carry_in, carry_out);
108-
carry_in = carry_out;
106+
s = add_with_carry(val[i], x.val[i], s.carry);
107+
val[i] = s.sum;
109108
}
110-
return carry_out;
109+
return s.carry;
111110
}
112111

113112
constexpr UInt<Bits> operator+(const UInt<Bits> &other) const {
114113
UInt<Bits> result;
115-
uint64_t carry_in = 0;
116-
uint64_t carry_out = 0;
114+
SumCarry<uint64_t> s{0, 0};
117115
for (size_t i = 0; i < WordCount; ++i) {
118-
result.val[i] = add_with_carry(val[i], other.val[i], carry_in, carry_out);
119-
carry_in = carry_out;
116+
s = add_with_carry(val[i], other.val[i], s.carry);
117+
result.val[i] = s.sum;
120118
}
121119
return result;
122120
}

libc/src/__support/builtin_wrappers.h

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
1111
#define LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
1212

13+
#include "named_pair.h"
1314
#include "src/__support/CPP/type_traits.h"
1415

1516
namespace __llvm_libc {
@@ -67,59 +68,131 @@ template <typename T> static inline int unsafe_clz(T val) {
6768
}
6869

6970
// Add with carry
71+
DEFINE_NAMED_PAIR_TEMPLATE(SumCarry, sum, carry);
72+
7073
template <typename T>
7174
inline constexpr cpp::enable_if_t<
72-
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, T>
73-
add_with_carry(T a, T b, T carry_in, T &carry_out) {
75+
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, SumCarry<T>>
76+
add_with_carry(T a, T b, T carry_in) {
7477
T tmp = a + carry_in;
7578
T sum = b + tmp;
76-
carry_out = (sum < b) || (tmp < a);
77-
return sum;
79+
T carry_out = (sum < b) || (tmp < a);
80+
return {sum, carry_out};
7881
}
7982

8083
#if __has_builtin(__builtin_addc)
8184
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
8285

8386
template <>
84-
inline unsigned char add_with_carry<unsigned char>(unsigned char a,
85-
unsigned char b,
86-
unsigned char carry_in,
87-
unsigned char &carry_out) {
88-
return __builtin_addcb(a, b, carry_in, &carry_out);
87+
inline SumCarry<unsigned char>
88+
add_with_carry<unsigned char>(unsigned char a, unsigned char b,
89+
unsigned char carry_in) {
90+
SumCarry<unsigned char> result{0, 0};
91+
result.sum = __builtin_addcb(a, b, carry_in, &result.carry);
92+
return result;
8993
}
9094

9195
template <>
92-
inline unsigned short
96+
inline SumCarry<unsigned short>
9397
add_with_carry<unsigned short>(unsigned short a, unsigned short b,
94-
unsigned short carry_in,
95-
unsigned short &carry_out) {
96-
return __builtin_addcs(a, b, carry_in, &carry_out);
98+
unsigned short carry_in) {
99+
SumCarry<unsigned short> result{0, 0};
100+
result.sum = __builtin_addcs(a, b, carry_in, &result.carry);
101+
return result;
97102
}
98103

99104
template <>
100-
inline unsigned int add_with_carry<unsigned int>(unsigned int a, unsigned int b,
101-
unsigned int carry_in,
102-
unsigned int &carry_out) {
103-
return __builtin_addc(a, b, carry_in, &carry_out);
105+
inline SumCarry<unsigned int>
106+
add_with_carry<unsigned int>(unsigned int a, unsigned int b,
107+
unsigned int carry_in) {
108+
SumCarry<unsigned int> result{0, 0};
109+
result.sum = __builtin_addc(a, b, carry_in, &result.carry);
110+
return result;
104111
}
105112

106113
template <>
107-
inline unsigned long add_with_carry<unsigned long>(unsigned long a,
108-
unsigned long b,
109-
unsigned long carry_in,
110-
unsigned long &carry_out) {
111-
return __builtin_addcl(a, b, carry_in, &carry_out);
114+
inline SumCarry<unsigned long>
115+
add_with_carry<unsigned long>(unsigned long a, unsigned long b,
116+
unsigned long carry_in) {
117+
SumCarry<unsigned long> result{0, 0};
118+
result.sum = __builtin_addcl(a, b, carry_in, &result.carry);
119+
return result;
112120
}
113121

114122
template <>
115-
inline unsigned long long
123+
inline SumCarry<unsigned long long>
116124
add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b,
117-
unsigned long long carry_in,
118-
unsigned long long &carry_out) {
119-
return __builtin_addcll(a, b, carry_in, &carry_out);
125+
unsigned long long carry_in) {
126+
SumCarry<unsigned long long> result{0, 0};
127+
result.sum = __builtin_addcll(a, b, carry_in, &result.carry);
128+
return result;
120129
}
130+
121131
#endif // __has_builtin(__builtin_addc)
122132

133+
// Subtract with borrow
134+
DEFINE_NAMED_PAIR_TEMPLATE(DiffBorrow, diff, borrow);
135+
136+
template <typename T>
137+
inline constexpr cpp::enable_if_t<
138+
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, DiffBorrow<T>>
139+
sub_with_borrow(T a, T b, T borrow_in) {
140+
T tmp = a - b;
141+
T diff = tmp - borrow_in;
142+
T borrow_out = (diff > tmp) || (tmp > a);
143+
return {diff, borrow_out};
144+
}
145+
146+
#if __has_builtin(__builtin_subc)
147+
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
148+
149+
template <>
150+
inline DiffBorrow<unsigned char>
151+
sub_with_borrow<unsigned char>(unsigned char a, unsigned char b,
152+
unsigned char borrow_in) {
153+
DiffBorrow<unsigned char> result{0, 0};
154+
result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow);
155+
return result;
156+
}
157+
158+
template <>
159+
inline DiffBorrow<unsigned short>
160+
sub_with_borrow<unsigned short>(unsigned short a, unsigned short b,
161+
unsigned short borrow_in) {
162+
DiffBorrow<unsigned short> result{0, 0};
163+
result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow);
164+
return result;
165+
}
166+
167+
template <>
168+
inline DiffBorrow<unsigned int>
169+
sub_with_borrow<unsigned int>(unsigned int a, unsigned int b,
170+
unsigned int borrow_in) {
171+
DiffBorrow<unsigned int> result{0, 0};
172+
result.diff = __builtin_subc(a, b, borrow_in, &result.borrow);
173+
return result;
174+
}
175+
176+
template <>
177+
inline DiffBorrow<unsigned long>
178+
sub_with_borrow<unsigned long>(unsigned long a, unsigned long b,
179+
unsigned long borrow_in) {
180+
DiffBorrow<unsigned long> result{0, 0};
181+
result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow);
182+
return result;
183+
}
184+
185+
template <>
186+
inline DiffBorrow<unsigned long long>
187+
sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b,
188+
unsigned long long borrow_in) {
189+
DiffBorrow<unsigned long long> result{0, 0};
190+
result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow);
191+
return result;
192+
}
193+
194+
#endif // __has_builtin(__builtin_subc)
195+
123196
} // namespace __llvm_libc
124197

125198
#endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H

libc/src/__support/integer_utils.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ inline NumberPair<uint64_t> full_mul<uint64_t>(uint64_t a, uint64_t b) {
4646
NumberPair<uint64_t> lo_hi = split(pa.lo * pb.hi); // exact
4747
NumberPair<uint64_t> hi_lo = split(pa.hi * pb.lo); // exact
4848

49-
uint64_t carry_in = 0;
50-
uint64_t carry_out = 0;
51-
uint64_t carry_unused = 0;
52-
prod.lo = add_with_carry(prod.lo, lo_hi.lo << 32, carry_in, carry_out);
53-
prod.hi = add_with_carry(prod.hi, lo_hi.hi, carry_out, carry_unused);
54-
prod.lo = add_with_carry(prod.lo, hi_lo.lo << 32, carry_in, carry_out);
55-
prod.hi = add_with_carry(prod.hi, hi_lo.hi, carry_out, carry_unused);
49+
auto r1 = add_with_carry(prod.lo, lo_hi.lo << 32, uint64_t(0));
50+
prod.lo = r1.sum;
51+
prod.hi = add_with_carry(prod.hi, lo_hi.hi, r1.carry).sum;
52+
53+
auto r2 = add_with_carry(prod.lo, hi_lo.lo << 32, uint64_t(0));
54+
prod.lo = r2.sum;
55+
prod.hi = add_with_carry(prod.hi, hi_lo.hi, r2.carry).sum;
5656

5757
return prod;
5858
#endif // __SIZEOF_INT128__

libc/src/__support/named_pair.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===-- Utilities for pairs of numbers. -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SUPPORT_NAMED_PAIR_H
10+
#define LLVM_LIBC_SRC_SUPPORT_NAMED_PAIR_H
11+
12+
#define DEFINE_NAMED_PAIR_TEMPLATE(Name, FirstField, SecondField) \
13+
template <typename T1, typename T2 = T1> struct Name { \
14+
T1 FirstField; \
15+
T2 SecondField; \
16+
}
17+
18+
#endif // LLVM_LIBC_SRC_SUPPORT_NAMED_PAIR_H

libc/src/__support/number_pair.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,13 @@
1010
#define LLVM_LIBC_SRC_SUPPORT_NUMBER_PAIR_H
1111

1212
#include "CPP/type_traits.h"
13+
#include "named_pair.h"
1314

1415
#include <stddef.h>
1516

1617
namespace __llvm_libc {
1718

18-
template <typename T> struct NumberPair {
19-
T lo;
20-
T hi;
21-
};
19+
DEFINE_NAMED_PAIR_TEMPLATE(NumberPair, lo, hi);
2220

2321
using DoubleDouble = NumberPair<double>;
2422

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ cc_library(
161161
hdrs = ["src/__support/number_pair.h"],
162162
deps = [
163163
"__support_cpp_type_traits",
164+
"__support_named_pair",
164165
":libc_root",
165166
],
166167
)
@@ -230,11 +231,18 @@ cc_library(
230231
],
231232
)
232233

234+
cc_library(
235+
name = "__support_named_pair",
236+
hdrs = ["src/__support/named_pair.h"],
237+
deps = [":libc_root"],
238+
)
239+
233240
cc_library(
234241
name = "__support_builtin_wrappers",
235242
hdrs = ["src/__support/builtin_wrappers.h"],
236243
deps = [
237244
":__support_cpp_type_traits",
245+
":__support_named_pair",
238246
":libc_root",
239247
],
240248
)

0 commit comments

Comments
 (0)