[compiler-rt] [compiler-rt] optimize __umodti3 (PR #82353)

Jan Schultke via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 20 04:43:38 PST 2024


https://github.com/Eisenwave created https://github.com/llvm/llvm-project/pull/82353

See https://github.com/llvm/llvm-project/issues/82183 for discussion.

This PR only fixes the missed optimization at a compiler-rt level. Future work still includes improving codegen so that no call to `__umodti3` is emitted.

>From 614edb3a1be3e6f559470afc5774e71cef7e41c2 Mon Sep 17 00:00:00 2001
From: Eisenwave <me at eisenwave.net>
Date: Tue, 20 Feb 2024 13:38:29 +0100
Subject: [PATCH 1/2] [compiler-rt] optimize __umodti3

---
 compiler-rt/lib/builtins/umodti3.c | 31 +++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/compiler-rt/lib/builtins/umodti3.c b/compiler-rt/lib/builtins/umodti3.c
index 8cc5cb6b88f784..c289fe33ebf6e3 100644
--- a/compiler-rt/lib/builtins/umodti3.c
+++ b/compiler-rt/lib/builtins/umodti3.c
@@ -14,12 +14,33 @@
 
 #ifdef CRT_HAS_128BIT
 
-// Returns: a % b
-
+/// Returns: a % b
 COMPILER_RT_ABI tu_int __umodti3(tu_int a, tu_int b) {
-  tu_int r;
-  __udivmodti4(a, b, &r);
-  return r;
+  utwords aWords = {.all = a};
+  utwords bWords = {.all = b};
+
+  // Optimization based on modular arithmetic:
+  //   (A_hi * 2^64 + A_lo) % B   =   ((A_hi % B) * 2^64 + A_lo) % B
+  //
+  // The first division on the right hand side is a 64-bit division.
+  // The second division has a 64-bit quotient, so divq is safe to use.
+  // Even if we don't have divq, it's faster to reduce the dividend bits prior
+  // to a 128-bit software division.
+  aWords.s.high = aWords.s.high % bWords.s.low;
+
+#if defined(__x86_64__)
+  du_int quotient;
+  du_int remainder;
+  __asm__("divq %[v]"
+          : "=a"(quotient), "=d"(remainder)
+          : [v] "r"(b), "a"(aWords.s.low), "d"(aWords.s.high));
+  (void)quotient;
+  return remainder;
+#else
+  tu_int remainder;
+  __udivmodti4(aWords.all, b, &remainder);
+  return (du_int)remainder;
+#endif
 }
 
 #endif // CRT_HAS_128BIT

>From be431fca47a034ff5df0c8026d43a9d1a075ffc0 Mon Sep 17 00:00:00 2001
From: Eisenwave <me at eisenwave.net>
Date: Tue, 20 Feb 2024 13:38:54 +0100
Subject: [PATCH 2/2] [compiler-rt] add two simple test cases

---
 compiler-rt/test/builtins/Unit/umodti3_test.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/compiler-rt/test/builtins/Unit/umodti3_test.c b/compiler-rt/test/builtins/Unit/umodti3_test.c
index 6efeb51a6252d2..2054cac5079139 100644
--- a/compiler-rt/test/builtins/Unit/umodti3_test.c
+++ b/compiler-rt/test/builtins/Unit/umodti3_test.c
@@ -41,6 +41,10 @@ int main()
         return 1;
     if (test__umodti3(2, 1, 0))
         return 1;
+    if (test__umodti3(123, 1000, 123))
+        return 1;
+    if (test__umodti3(123, 77, 46))
+        return 1;
     if (test__umodti3(make_tu(0x8000000000000000uLL, 0), 1, 0x0uLL))
         return 1;
     if (test__umodti3(make_tu(0x8000000000000000uLL, 0), 2, 0x0uLL))



More information about the llvm-commits mailing list