Microoptimization: Use a form of byteswapping that gcc realizes that is auto-zero...
authorSteinar H. Gunderson <sesse@debian.org>
Sun, 31 May 2009 23:54:31 +0000 (01:54 +0200)
committerSteinar H. Gunderson <sesse@debian.org>
Sun, 31 May 2009 23:54:31 +0000 (01:54 +0200)
bitsource.h

index 60744b3..f2f164d 100644 (file)
 typedef uint64_t bitreservoir_t;
 typedef uint32_t bitreservoir_fill_t;
 
-static inline bitreservoir_fill_t read_bitreservoir_fill(uint8_t* source)
+// Note: We return bitreservoir_t here, so we can get implicit zero extension on amd64.
+static inline bitreservoir_t read_bitreservoir_fill(uint8_t* source)
 {
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+       bitreservoir_t ret;
+       asm("bswapl %1" : "=r" (ret) : "0" (*(bitreservoir_fill_t*)(source)));
+       return ret;
+#else
        return ntohl(*(bitreservoir_fill_t*)(source));
+#endif
 }
 
 static const unsigned BITRESERVOIR_SIZE = 8 * sizeof(bitreservoir_t);
@@ -71,7 +78,7 @@ static inline void possibly_refill(struct bit_source* source, unsigned num_bits)
        // Slower path (~99% of remaining invocations?)
        assert(source->bits_available + BITRESERVOIR_FILL_SIZE < BITRESERVOIR_SIZE);
        if (source->bytes_available >= sizeof(bitreservoir_fill_t)) {
-               bitreservoir_fill_t fill = read_bitreservoir_fill(source->byte_read_ptr);
+               bitreservoir_t fill = read_bitreservoir_fill(source->byte_read_ptr);
                source->byte_read_ptr += sizeof(bitreservoir_fill_t);
                source->bytes_available -= sizeof(bitreservoir_fill_t);
                source->bits |= (bitreservoir_t)fill << (BITRESERVOIR_SIZE - BITRESERVOIR_FILL_SIZE - source->bits_available);