Re: [PATCH 2/2] uapi: Refactor __GENMASK_ULL() for speed-up

From: I Hsin Cheng
Date: Wed Feb 12 2025 - 07:39:22 EST


On Tue, Feb 11, 2025 at 10:30:45PM +0000, David Laight wrote:
> On Wed, 12 Feb 2025 00:24:12 +0800
> I Hsin Cheng <richard120310@xxxxxxxxx> wrote:
>
> > The calculation of "((~_ULL(0)) - (_ULL(1) << (l)) + 1)" is to generate
> > a bitmask with "l" trailing zeroes, which is equivalent to
> > "(~_ULL(0) << (l))".
>
> Yes, and if you look through the commit history you'll see it was changed
> to avoid a compiler warning about the shift losing significant bits.
> So you are just reverting that change and the compiler warnings will
> reappear.
>
> For non-constants I suspect that (2ul << hi) - (1ul << lo) is the
> best answer.
> But the compiler (clang with some options?) will still complain
> for constants when trying to set the high bit.
>
> That version also doesn't need BITS_PER_[U]LONG.
> While that is valid for C, the _ULL() are there for the assembler
> (when they are no-ops) so there is no way asm copies can be right
> for both GENMASK() ans GENMASK_ULL().
>
> David

Hi David,

Thanks for the review!

> Yes, and if you look through the commit history you'll see it was changed
> to avoid a compiler warning about the shift losing significant bits.

I've browse through the commits of include/linux/bits.h , where
GENMASK() was placed under. Though I didn't find specific commit of it,
would you be so kind to paste the link of the commit?

I assume you're talking about warnings like the following?
warning: left shift count >= width of type [-Wshift-count-overflow]

If this is the case then it happens for the current version as well, I
mean from the perspective of operations, "(~_ULL(0) << (l))" and
"(_ULL(1) << (1))" are basically the same, they all shift a constant
left with an amount of "l". When "l" is large enough the compiler will
complain about losing msb.

> While that is valid for C, the _ULL() are there for the assembler
> (when they are no-ops) so there is no way asm copies can be right
> for both GENMASK() ans GENMASK_ULL().

I don't understand this part sorry, if asm copies can't be right for
"~_ULL(0) << (l)" , how can it be right for "(_ULL(1) << (l))" ?
At least from my pespective these 2 ops only differs at the value of
constant. Please let me know about it, I'm not familiar with assembler
and would love to know more about it. Thanks.

Best regards,
I Hsin Cheng