Search Non ASCII with SSE2

最近はほとんどの x86 CPU が SSE と SSE2 をサポートしているので、SSE2 も使ってみましょう。やってることはワード単位の場合と大して変わりません。ちなみに、速度は 10000 文字を 1000 万回で、上記のワードごと 25 秒に対し 20 秒・・・、あまりかわりません。

#ifdef __SSE2__
# include <emmintrin.h>

const char *
search_nonascii_sse(const char *p, const char *e)
{
    if (16 < e - p) {
	if (!_mm_movemask_epi8(_mm_loadu_si128((__m128i const*)p))) {
	    const intptr_tlowbits = sizeof(__m128i) - 1;
	    const __m128i *s, *t;
	    s = (const __m128i *)(~lowbits & ((intptr_t)p + lowbits));
	    t = (const __m128i *)(~lowbits & (intptr_t)e);
	    for (; s < t; ++s) {
		if (_mm_movemask_epi8(_mm_load_si128(s)))
		    break;
	    }
	    p = (const char *)s;
	}
    }
    switch (e - p) {
    case 15: if (!isascii(*p)) return p; ++p;
    case 14: if (!isascii(*p)) return p; ++p;
    case 13: if (!isascii(*p)) return p; ++p;
    case 12: if (!isascii(*p)) return p; ++p;
    case 11: if (!isascii(*p)) return p; ++p;
    case 10: if (!isascii(*p)) return p; ++p;
    case 9: if (!isascii(*p)) return p; ++p;
    case 8: if (!isascii(*p)) return p; ++p;
    case 7: if (!isascii(*p)) return p; ++p;
    case 6: if (!isascii(*p)) return p; ++p;
    case 5: if (!isascii(*p)) return p; ++p;
    case 4: if (!isascii(*p)) return p; ++p;
    case 3: if (!isascii(*p)) return p; ++p;
    case 2: if (!isascii(*p)) return p; ++p;
    case 1: if (!isascii(*p)) return p;
    }
    return NULL;
}
#endif