On Mon, May 17, 2021 at 04:36:43PM +0300, Dan Carpenter wrote: > On Mon, May 17, 2021 at 10:07:20AM +0300, Andy Shevchenko wrote: > > On Fri, May 14, 2021 at 12:26 PM Dan Carpenter <dan.carpenter@xxxxxxxxxx> wrote: > > > On Thu, May 13, 2021 at 09:52:27AM +0100, Colin King wrote: > > > > ... > > > > > > const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); > > > > > > > > map[index] &= ~(0xFFFFFFFFul << offset); > > > > - map[index] |= v << offset; > > > > + map[index] |= (unsigned long)v << offset; > > > > > > Doing a shift by BIT(5) is super weird. > > > > Not the first place in the kernel with such a trick. > > > > > It looks like a double shift > > > bug and should probably trigger a static checker warning. It's like > > > when people do BIT(BIT(5)). > > > > > > It would be more readable to write it as: > > > > > > int shift = (bit % BITS_PER_LONG) ? 32 : 0; > > > > Usually this code is in a kinda fast path. Have you checked if the > > compiler generates the same or better code when you are using ternary? > > I wrote a little benchmark to see which was faster and they're the same > as far as I can see. Thanks for checking. Besides the fact that offset should be 0 for 32-bit always and if compiler can proof that... The test below doesn't take into account the exact trick is used for offset (i.e. implicit dependency between BITS_PER_LONG, size of unsigned long, and using 5th bit out of value). I don't know if compiler can properly optimize the ternary in this case (but it looks like it should generate the same code). That said, I would rather to see the diff between assembly of the exact function before and after your proposal. > static inline __attribute__((__gnu_inline__)) unsigned long xgpio_set_value_orig(unsigned long *map, int bit, u32 v) > { > int shift = (bit % 64) & ((((1UL))) << (5)); > return v << shift; > } > > static inline __attribute__((__gnu_inline__)) unsigned long xgpio_set_value_new(unsigned long *map, int bit, u32 v) > { > int shift = (bit % 64) ? 32 : 0; > return v << shift; > } > > int main(void) > { > int i; > > for (i = 0; i < INT_MAX; i++) > xgpio_set_value_orig(NULL, i, 0); > > // for (i = 0; i < INT_MAX; i++) > // xgpio_set_value_new(NULL, i, 0); > > return 0; > } > -- With Best Regards, Andy Shevchenko