[libc-commits] [libc] 926dd32 - [libc][math] Improve the performance of subtraction for UInt<>.
Tue Ly via libc-commits
libc-commits at lists.llvm.org
Wed Nov 30 07:51:30 PST 2022
Author: Tue Ly
Date: 2022-11-30T10:51:02-05:00
New Revision: 926dd32aab1d79dbd85639e5eaf7b4d3cd086af6
URL: https://github.com/llvm/llvm-project/commit/926dd32aab1d79dbd85639e5eaf7b4d3cd086af6
DIFF: https://github.com/llvm/llvm-project/commit/926dd32aab1d79dbd85639e5eaf7b4d3cd086af6.diff
LOG: [libc][math] Improve the performance of subtraction for UInt<>.
Use built-in sub_with_borrow to improve the performance of subtraction
for UInt<>.
Microbenchmark: https://quick-bench.com/q/UEg6Z6VK4PP2yLBtTi9C0cL9xpY
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D138506
Added:
Modified:
libc/src/__support/UInt.h
Removed:
################################################################################
diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index 78dd8fadda0f8..cec08b3530bb6 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -97,9 +97,6 @@ template <size_t Bits> struct UInt {
// Add x to this number and store the result in this number.
// Returns the carry value produced by the addition operation.
- // To prevent overflow from intermediate results, we use the following
- // property of unsigned integers:
- // x + (~x) = 2^(sizeof(x)) - 1.
constexpr uint64_t add(const UInt<Bits> &x) {
SumCarry<uint64_t> s{0, 0};
for (size_t i = 0; i < WordCount; ++i) {
@@ -119,48 +116,33 @@ template <size_t Bits> struct UInt {
return result;
}
- constexpr UInt<Bits> operator+=(const UInt<Bits> &other) {
+ constexpr UInt<Bits> &operator+=(const UInt<Bits> &other) {
add(other); // Returned carry value is ignored.
return *this;
}
// Subtract x to this number and store the result in this number.
// Returns the carry value produced by the subtraction operation.
- // To prevent overflow from intermediate results, we use the following
- // property of unsigned integers:
- // x + (~x) = 2^(sizeof(x)) - 1,
- // So:
- // -x = ((~x) + 1) + (-2^(sizeof(x))),
- // where 2^(sizeof(x)) is represented by the carry bit.
constexpr uint64_t sub(const UInt<Bits> &x) {
- bool carry = false;
+ DiffBorrow<uint64_t> d{0, 0};
for (size_t i = 0; i < WordCount; ++i) {
- if (!carry) {
- if (val[i] >= x.val[i])
- val[i] -= x.val[i];
- else {
- val[i] += (~x.val[i]) + 1;
- carry = true;
- }
- } else {
- if (val[i] > x.val[i]) {
- val[i] -= x.val[i] + 1;
- carry = false;
- } else
- val[i] += ~x.val[i];
- }
+ d = sub_with_borrow(val[i], x.val[i], d.borrow);
+ val[i] = d.
diff ;
}
- return carry ? 1 : 0;
+ return d.borrow;
}
constexpr UInt<Bits> operator-(const UInt<Bits> &other) const {
- UInt<Bits> result(*this);
- result.sub(other);
- // TODO(lntue): Set overflow flag / errno when carry is true.
+ UInt<Bits> result;
+ DiffBorrow<uint64_t> d{0, 0};
+ for (size_t i = 0; i < WordCount; ++i) {
+ d = sub_with_borrow(val[i], other.val[i], d.borrow);
+ result.val[i] = d.
diff ;
+ }
return result;
}
- constexpr UInt<Bits> operator-=(const UInt<Bits> &other) {
+ constexpr UInt<Bits> &operator-=(const UInt<Bits> &other) {
// TODO(lntue): Set overflow flag / errno when carry is true.
sub(other);
return *this;
More information about the libc-commits
mailing list