[libc-commits] [PATCH] D138506: [libc][math] Improve the performance of subtraction for UInt<>.

Tue Ly via Phabricator via libc-commits libc-commits at lists.llvm.org
Tue Nov 22 08:38:33 PST 2022


lntue created this revision.
lntue added reviewers: michaelrj, sivachandra.
Herald added subscribers: ecnelises, tschuett.
Herald added projects: libc-project, All.
lntue requested review of this revision.

Use built-in sub_with_borrow to improve the performance of subtraction
for UInt<>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138506

Files:
  libc/src/__support/UInt.h


Index: libc/src/__support/UInt.h
===================================================================
--- libc/src/__support/UInt.h
+++ libc/src/__support/UInt.h
@@ -97,9 +97,6 @@
 
   // 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 @@
     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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D138506.477214.patch
Type: text/x-patch
Size: 2529 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20221122/4dfa0d02/attachment.bin>


More information about the libc-commits mailing list