4 ms·
Sure, but if you look at the implementation in the article, that's a much longer dependency chain: *c = (uint32_t)(s[0] & masks[len]) << 18; *c |= (ui
by ot 9y ago
Sure, but if you look at the implementation in the article, that's a much longer dependency chain:
*c = (uint32_t)(s[0] & masks[len]) << 18;
*c |= (uint32_t)(s[1] & 0x3f) << 12;
*c |= (uint32_t)(s[2] & 0x3f) << 6;
*c |= (uint32_t)(s[3] & 0x3f) << 0;
*c >>= shiftc[len];
/* Accumulate the various error conditions. */
*e = (*c < mins[len]) << 6;
*e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
*e |= (s[1] & 0xc0) >> 2;
*e |= (s[2] & 0xc0) >> 4;
*e |= (s[3] ) >> 6;
*e ^= 0x2a; // top two bits of each tail byte correct?
*e >>= shifte[len];
Plus, all those loads are not making it easy for the processor to pipeline.
And
*e = (*c < mins[len]) << 6;
is really a CMOV in disguise :)
- userbinator 9y agois really a CMOV in disguise :) I don't see how using CMOV would be appropriate there --- I'd compile it as something more like this: ; eax = *c, ebx = mins[len] cmp eax, ebx sbb eax, eax and eax, 64 ; eax = (*c < mins[len]) << 6