The code is not optimal, because there are implicit conversions to int (32-bit values) which are quite expansive. There should be explicit casts to uint16_t, like this: dest.r = uint16_t(uint16_t(dest.r * invAlpha) + uint16_t(c.r * c.a)) >> 8;
dest.r = uint16_t(dest.r * invAlpha + c.r * c.a) >> 8;
Seems to get all of the benefit. The result is 34 instructions in the loop. (Was 38).Amazingly, switching from gcc 8.2 to gcc trunk, reduces the instructions in the loop to 18. See https://godbolt.org/z/sEvz2w