emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master e4769b20f1 3/4: Restrict string-lessp vectorisation to safe archi


From: Mattias Engdegård
Subject: master e4769b20f1 3/4: Restrict string-lessp vectorisation to safe architectures
Date: Sat, 8 Oct 2022 12:49:08 -0400 (EDT)

branch: master
commit e4769b20f166aeb78d66d1ac1db4628f72683372
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>

    Restrict string-lessp vectorisation to safe architectures
    
    * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): New.
    (Fstring_lessp): Only use word operations where safe, because string
    data from purespace may be unaligned.
---
 src/fns.c | 40 ++++++++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/fns.c b/src/fns.c
index bc4915eb25..5eab35a564 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -433,6 +433,21 @@ If string STR1 is greater, the value is a positive number 
N;
   return Qt;
 }
 
+/* Check whether the platform allows access to unaligned addresses for
+   size_t integers without trapping or undue penalty (a few cycles is OK).
+
+   This whitelist is incomplete but since it is only used to improve
+   performance, omitting cases is safe.  */
+#if defined __x86_64__|| defined __amd64__     \
+    || defined __i386__ || defined __i386      \
+    || defined __arm64__ || defined __aarch64__        \
+    || defined __powerpc__ || defined __powerpc        \
+    || defined __ppc__ || defined __ppc
+#define HAVE_FAST_UNALIGNED_ACCESS 1
+#else
+#define HAVE_FAST_UNALIGNED_ACCESS 0
+#endif
+
 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
        doc: /* Return non-nil if STRING1 is less than STRING2 in lexicographic 
order.
 Case is significant.
@@ -468,18 +483,23 @@ Symbols are also allowed; their print names are used 
instead.  */)
       ptrdiff_t nb1 = SBYTES (string1);
       ptrdiff_t nb2 = SBYTES (string2);
       ptrdiff_t nb = min (nb1, nb2);
-
-      /* First compare entire machine words.  (String data is allocated
-        with word alignment.)  */
-      typedef size_t word_t;
-      int ws = sizeof (word_t);
-      const word_t *w1 = (const word_t *) SDATA (string1);
-      const word_t *w2 = (const word_t *) SDATA (string2);
       ptrdiff_t b = 0;
-      while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws])
-       b += ws;
 
-      /* Scan forward to the differing byte (at most ws-1 bytes).  */
+      /* String data is normally allocated with word alignment, but
+        there are exceptions (notably pure strings) so we restrict the
+        wordwise skipping to safe architectures.  */
+      if (HAVE_FAST_UNALIGNED_ACCESS)
+       {
+         /* First compare entire machine words.  */
+         typedef size_t word_t;
+         int ws = sizeof (word_t);
+         const word_t *w1 = (const word_t *) SDATA (string1);
+         const word_t *w2 = (const word_t *) SDATA (string2);
+         while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws])
+           b += ws;
+       }
+
+      /* Scan forward to the differing byte.  */
       while (b < nb && SREF (string1, b) == SREF (string2, b))
        b++;
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]