Skip to content

Commit 2a535a9

Browse files
Sebastian Popnikic
authored andcommitted
[AArch64] Use crc32 instructions when available
The time goes from 0.838s down to 0.029s (a 28x speedup) on a Graviton A1 instance and the following benchmark: function simple_crc32() { $a = "foo"; for ($i = 0; $i < 10000; $i++) { crc32($a); $a .= "o".$i; } }
1 parent ba8c489 commit 2a535a9

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

ext/standard/crc32.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,32 @@
2020
#include "basic_functions.h"
2121
#include "crc32.h"
2222

23+
#if defined(__aarch64__)
24+
# pragma GCC target ("+nothing+crc")
25+
# include <arm_acle.h>
26+
# if defined(__linux__)
27+
# include <sys/auxv.h>
28+
# include <asm/hwcap.h>
29+
# endif
30+
31+
static inline int has_crc32_insn() {
32+
/* Only go through the runtime detection once. */
33+
static int res = -1;
34+
if (res != -1)
35+
return res;
36+
# if defined(HWCAP_CRC32)
37+
res = getauxval(AT_HWCAP) & HWCAP_CRC32;
38+
return res;
39+
# elif defined(HWCAP2_CRC32)
40+
res = getauxval(AT_HWCAP2) & HWCAP2_CRC32;
41+
return res;
42+
# else
43+
res = 0;
44+
return res;
45+
# endif
46+
}
47+
#endif
48+
2349
/* {{{ proto string crc32(string str)
2450
Calculate the crc32 polynomial of a string */
2551
PHP_NAMED_FUNCTION(php_if_crc32)
@@ -35,6 +61,30 @@ PHP_NAMED_FUNCTION(php_if_crc32)
3561

3662
crc = crcinit^0xFFFFFFFF;
3763

64+
#if defined(__aarch64__)
65+
if (has_crc32_insn()) {
66+
while(nr >= sizeof(uint64_t)) {
67+
crc = __crc32d(crc, *(uint64_t *)p);
68+
p += sizeof(uint64_t);
69+
nr -= sizeof(uint64_t);
70+
}
71+
if (nr >= sizeof(int32_t)) {
72+
crc = __crc32w(crc, *(uint32_t *)p);
73+
p += sizeof(uint32_t);
74+
nr -= sizeof(uint32_t);
75+
}
76+
if (nr >= sizeof(int16_t)) {
77+
crc = __crc32h(crc, *(uint16_t *)p);
78+
p += sizeof(uint16_t);
79+
nr -= sizeof(uint16_t);
80+
}
81+
if (nr) {
82+
crc = __crc32b(crc, *p);
83+
p += sizeof(uint8_t);
84+
nr -= sizeof(uint8_t);
85+
}
86+
}
87+
#endif
3888
for (; nr--; ++p) {
3989
crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*p)) & 0xFF ];
4090
}

0 commit comments

Comments
 (0)