Skip to content

Commit b06449d

Browse files
authored
Merge pull request #2 from ENM1989/ENM1989-patch-1
Update zend_operators.c
2 parents cab57c4 + 65fa7b2 commit b06449d

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

Zend/zend_operators.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3725,6 +3725,40 @@ static zend_always_inline void zend_memnstr_ex_pre(unsigned int td[], const char
37253725

37263726
ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
37273727
{
3728+
#if defined(__SSE2__)
3729+
if (needle_len >= 4) {
3730+
const char *p;
3731+
__m128i first_chars = _mm_set1_epi8(needle[0]);
3732+
__m128i last_chars = _mm_set1_epi8(needle[needle_len - 1]);
3733+
3734+
for (p = haystack; p <= end - needle_len; p += 16) {
3735+
__m128i haystack_first_chars = _mm_loadu_si128((__m128i*)p);
3736+
__m128i haystack_last_chars = _mm_loadu_si128((__m128i*)(p + needle_len - 1));
3737+
__m128i eq_first = _mm_cmpeq_epi8(first_chars, haystack_first_chars);
3738+
__m128i eq_last = _mm_cmpeq_epi8(last_chars, haystack_last_chars);
3739+
unsigned long mask = _mm_movemask_epi8(_mm_and_si128(eq_first, eq_last));
3740+
3741+
while (mask > 0) {
3742+
unsigned long bit = 1UL << __builtin_ctzl(mask);
3743+
size_t ofs = __builtin_ctzl(mask);
3744+
if (memcmp(p + ofs + 1, needle + 1, needle_len - 2) == 0) {
3745+
return p + ofs;
3746+
}
3747+
mask &= ~bit;
3748+
}
3749+
}
3750+
3751+
// Handle the remainder of the string if its length is not a multiple of 16
3752+
for (; p <= end - needle_len; p++) {
3753+
if (p[0] == needle[0] && memcmp(p + 1, needle + 1, needle_len - 1) == 0) {
3754+
return p;
3755+
}
3756+
}
3757+
3758+
return NULL;
3759+
}
3760+
#endif
3761+
37283762
unsigned int td[256];
37293763
size_t i;
37303764
const char *p;
@@ -3739,12 +3773,7 @@ ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const c
37393773
end -= needle_len;
37403774

37413775
while (p <= end) {
3742-
for (i = 0; i < needle_len; i++) {
3743-
if (needle[i] != p[i]) {
3744-
break;
3745-
}
3746-
}
3747-
if (i == needle_len) {
3776+
if (memcmp(p, needle, needle_len) == 0) {
37483777
return p;
37493778
}
37503779
if (UNEXPECTED(p == end)) {

0 commit comments

Comments
 (0)