on master help sign in
encodeUtf8_2: add fast paths for x86_64 and i386

This helps performance a lot in most cases: up to 2x faster, in fact. The exception seems to be Japanese, which is slowed down by about 10%.

commitd5bad1f0e33e05de2813ddc99f474067aa1144f3 authorBryan O'Sullivan <bos@serpentine.com> dateTue 7 Jan 2014, 21:36 (13 years ago) parentdf36f17
1 file changed+53−1
cbits/cbits.c+53−1
cbits/cbits.c+53−1
@@ -240,11 +240,63 @@ _hs_text_encode_utf8(uint8_t **destp, const uint16_t *src, size_t srcoff,
240240 src += srcoff;
241241 srcend = src + srclen;
242242
243+ ascii:
244+#if defined(__x86_64__)
245+ while (srcend - src >= 4) {
246+ uint64_t w = *((uint64_t *) src);
247+ uint16_t a = w & 0xFFFF, b = (w >> 16) & 0xFFFF, c = (w >> 32) & 0xFFFF,
248+ d = w >> 48;
249+
250+ if ((w & 0xFF80FF80FF80FF80ULL) == 0) {
251+ *dest++ = a;
252+ *dest++ = b;
253+ *dest++ = c;
254+ *dest++ = d;
255+ }
256+ else if ((w & 0xF800F800F800F800ULL) == 0) {
257+ *dest++ = (a >> 6) | 0xC0;
258+ *dest++ = (a & 0x3f) | 0x80;
259+ *dest++ = (b >> 6) | 0xC0;
260+ *dest++ = (b & 0x3f) | 0x80;
261+ *dest++ = (c >> 6) | 0xC0;
262+ *dest++ = (c & 0x3f) | 0x80;
263+ *dest++ = (d >> 6) | 0xC0;
264+ *dest++ = (d & 0x3f) | 0x80;
265+ }
266+ else break;
267+ src += 4;
268+ }
269+#endif
270+
271+#if defined(__i386__)
272+ while (srcend - src >= 2) {
273+ uint32_t w = *((uint32_t *) src);
274+ uint16_t a = w & 0xFFFF, b = w >> 16;
275+
276+ if ((w & 0xFF80FF80) == 0) {
277+ *dest++ = a;
278+ *dest++ = b;
279+ }
280+ else if ((w & 0xF800F800) == 0) {
281+ *dest++ = (a >> 6) | 0xC0;
282+ *dest++ = (a & 0x3f) | 0x80;
283+ *dest++ = (b >> 6) | 0xC0;
284+ *dest++ = (b & 0x3f) | 0x80;
285+ }
286+ else break;
287+ src += 2;
288+ }
289+#endif
290+
243291 while (src < srcend) {
244292 uint16_t w = *src++;
245293
246− if (w <= 0x7F)
294+ if (w <= 0x7F) {
247295 *dest++ = w;
296+ /* An ASCII byte is likely to begin a run of ASCII bytes.
297+ Falling back into the fast path really helps performance. */
298+ goto ascii;
299+ }
248300 else if (w <= 0x7FF) {
249301 *dest++ = (w >> 6) | 0xC0;
250302 *dest++ = (w & 0x3f) | 0x80;