On Wed, 05 Apr 2023, Steven Price <steven.price@xxxxxxx> wrote: > On 31/03/2023 09:31, Jani Nikula wrote: >> On Thu, 30 Mar 2023, Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> wrote: >>> On Thu, 30 Mar 2023 21:53:03 +0000 David Laight <David.Laight@xxxxxxxxxx> wrote: >>> >>>>> But wouldn't all these issues be addressed by simply doing >>>>> >>>>> #define is_power_of_2(n) (n != 0 && ((n & (n - 1)) == 0)) >>>>> >>>>> ? >>>>> >>>>> (With suitable tweaks to avoid evaluating `n' more than once) >>>> >>>> I think you need to use the 'horrid tricks' from min() to get >>>> a constant expression from constant inputs. >>> >>> This >>> >>> --- a/include/linux/log2.h~a >>> +++ a/include/linux/log2.h >>> @@ -41,11 +41,11 @@ int __ilog2_u64(u64 n) >>> * *not* considered a power of two. >>> * Return: true if @n is a power of 2, otherwise false. >>> */ >>> -static inline __attribute__((const)) >>> -bool is_power_of_2(unsigned long n) >>> -{ >>> - return (n != 0 && ((n & (n - 1)) == 0)); >>> -} >>> +#define is_power_of_2(_n) \ >>> + ({ \ >>> + typeof(_n) n = (_n); \ >>> + n != 0 && ((n & (n - 1)) == 0); \ >>> + }) >>> >>> /** >>> * __roundup_pow_of_two() - round up to nearest power of two >>> _ >>> >>> worked for me in a simple test. >>> >>> --- a/fs/open.c~b >>> +++ a/fs/open.c >>> @@ -1564,3 +1564,10 @@ int stream_open(struct inode *inode, str >>> } >>> >>> EXPORT_SYMBOL(stream_open); >>> + >>> +#include <linux/log2.h> >>> + >>> +int foo(void) >>> +{ >>> + return is_power_of_2(43); >>> +} >>> _ >>> >>> >>> foo: >>> # fs/open.c:1573: } >>> xorl %eax, %eax # >>> ret >>> >>> >>> Is there some more tricky situation where it breaks? >> >> It doesn't work with BUILD_BUG_ON_ZERO(). > > Like most programming problems, you just need another layer of > indirection! The below works for me in all the cases I could think of > (including __uint128_t). > > > #define __IS_POWER_OF_2(n) (n != 0 && ((n & (n - 1)) == 0)) > > #define _IS_POWER_OF_2(n, unique_n) \ > ({ \ > typeof(n) unique_n = (n); \ > __IS_POWER_OF_2(unique_n); \ > }) > > #define is_power_of_2(n) \ > __builtin_choose_expr(__is_constexpr((n)), \ > __IS_POWER_OF_2((n)), \ > _IS_POWER_OF_2(n, __UNIQUE_ID(_n))) > > > Although Jani's original might be easier to understand. I dropped the ball since I couldn't make heads or tails what I should be doing. And a year has passed. I'll note that the kernel has a number of helpers for "is power of 2" for u64 and for constant expressions, outside of log2.h. I tried to make is_power_of_2() work for all the cases. Would it be more palatable if I just added all the variants separately to log2.h? - Leave is_power_of_2() as is - Add is_power_of_2_u64() for 32-bit build compatible 64-bit checks - Add IS_POWER_OF_2() macro for constant expressions Please just tell me what to do and I'll do it. BR, Jani. -- Jani Nikula, Intel