]> granicus.if.org Git - php/commitdiff
[AArch64] use rev64 to reverse strings
authorSebastian Pop <spop@amazon.com>
Fri, 3 May 2019 15:17:41 +0000 (15:17 +0000)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 7 May 2019 08:40:45 +0000 (10:40 +0200)
The execution time goes from 4.388s down to 0.563s on a Graviton A1
instance for the benchmark:

function reverse_strings() {
    $a = "foo";
    for ($i = 0; $i < 100000; $i++) {
        strrev($a);
        $a .= "o";
    }
}

ext/standard/string.c

index 0ec4bf77a89239239563744f33300238a03d0e90..706828c6a9c17425901374258e182201cd337810 100644 (file)
@@ -3536,6 +3536,8 @@ PHP_FUNCTION(strtr)
    Reverse a string */
 #if ZEND_INTRIN_SSSE3_NATIVE
 #include <tmmintrin.h>
+#elif defined(__aarch64__)
+#include <arm_neon.h>
 #endif
 PHP_FUNCTION(strrev)
 {
@@ -3568,6 +3570,19 @@ PHP_FUNCTION(strrev)
                        e -= 16;
                } while (e - s > 15);
        }
+#elif defined(__aarch64__)
+       if (e - s > 15) {
+               do {
+                       const uint8x16_t str = vld1q_u8((uint8_t *)(e - 15));
+                       /* Synthesize rev128 with a rev64 + ext. */
+                       const uint8x16_t rev = vrev64q_u8(str);
+                       const uint8x16_t ext = (uint8x16_t)
+                               vextq_u64((uint64x2_t)rev, (uint64x2_t)rev, 1);
+                       vst1q_u8((uint8_t *)p, ext);
+                       p += 16;
+                       e -= 16;
+               } while (e - s > 15);
+       }
 #endif
        while (e >= s) {
                *p++ = *e--;