lkml.org 
[lkml]   [2023]   [Mar]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: [PATCH 0/4] log2: make is_power_of_2() more generic
    Date
    On Thu, 30 Mar 2023, Andrew Morton <akpm@linux-foundation.org> wrote:
    > On Thu, 30 Mar 2023 21:53:03 +0000 David Laight <David.Laight@ACULAB.COM> 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().

    test.c:
    #define IS_POWER_OF_2(_n) \
    ({ \
    typeof(_n) n = (_n); \
    n != 0 && ((n & (n - 1)) == 0); \
    })

    #define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))

    #define FOO(n) ((n) + BUILD_BUG_ON_ZERO(!IS_POWER_OF_2(n)))

    int main(void)
    {
    return FOO(2);
    }

    $ gcc test.c
    test.c: In function ‘main’:
    test.c:16:51: error: bit-field ‘<anonymous>’ width not an integer constant
    16 | #define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))
    | ^
    test.c:18:23: note: in expansion of macro ‘BUILD_BUG_ON_ZERO’
    18 | #define FOO(n) ((n) + BUILD_BUG_ON_ZERO(!IS_POWER_OF_2(n)))
    | ^~~~~~~~~~~~~~~~~
    test.c:22:9: note: in expansion of macro ‘FOO’
    22 | return FOO(2);
    | ^~~


    BR,
    Jani.

    --
    Jani Nikula, Intel Open Source Graphics Center

    \
     
     \ /
      Last update: 2023-03-31 10:32    [W:2.914 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site