From: Tue Ly Date: Tue, 22 Nov 2022 16:33:40 +0000 (-0500) Subject: [libc][math] Improve the performance of subtraction for UInt<>. X-Git-Tag: upstream/17.0.6~25860 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=926dd32aab1d79dbd85639e5eaf7b4d3cd086af6;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index 78dd8fa..cec08b3 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -97,9 +97,6 @@ template 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 &x) { SumCarry s{0, 0}; for (size_t i = 0; i < WordCount; ++i) { @@ -119,48 +116,33 @@ template struct UInt { return result; } - constexpr UInt operator+=(const UInt &other) { + constexpr UInt &operator+=(const UInt &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 &x) { - bool carry = false; + DiffBorrow 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 operator-(const UInt &other) const { - UInt result(*this); - result.sub(other); - // TODO(lntue): Set overflow flag / errno when carry is true. + UInt result; + DiffBorrow 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 operator-=(const UInt &other) { + constexpr UInt &operator-=(const UInt &other) { // TODO(lntue): Set overflow flag / errno when carry is true. sub(other); return *this;