Mettle

unbounded-shiftA right shift whose input cannot be bounded

Reported by --explain after a verdict.

mettle explain unbounded-shift

Integer lanes are 32 bits wide. + - * & | ^ << are congruent mod 2^32, so the low 32 bits of a result depend only on the low 32 bits of its inputs and a lane reproduces them whatever width the scalar code used. >> is the exception: it reads bits back DOWN, so a lane that wrapped where the scalar did not would shift different bits in.

The kernel takes a right shift only where the shifted value is provably inside int32, and a multiply is not provable on its own. This is refused:

dst[i] = (r[i]*77 + g[i]*150 + b[i]*29) >> 8;

Masking bounds it, at the cost of one op per lane, and this vectorizes:

dst[i] = ((r[i]*77 + g[i]*150 + b[i]*29) & 65535) >> 8;

Keep the destination int32. Narrowing the store to a uint8* puts the loop outside the kernels for a separate reason, so masking alone will not move it.

Related