Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1660649 > unrolled thread

Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations

Started byAndy Shevchenko <andy.shevchenko@gmail.com>
First post2017-06-08 03:50 +0200
Last post2017-06-08 16:50 +0200
Articles 5 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations Andy Shevchenko <andy.shevchenko@gmail.com> - 2017-06-08 03:50 +0200
    Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations Matthew Wilcox <willy@infradead.org> - 2017-06-08 05:00 +0200
      Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations Andy Shevchenko <andy.shevchenko@gmail.com> - 2017-06-08 14:40 +0200
        Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2017-06-08 15:50 +0200
          Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations Andy Shevchenko <andy.shevchenko@gmail.com> - 2017-06-08 16:50 +0200

#1660649 — Re: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations

FromAndy Shevchenko <andy.shevchenko@gmail.com>
Date2017-06-08 03:50 +0200
SubjectRe: [PATCH 3/3] bitmap: Use memcmp optimisation in more situations
Message-ID<tPUKe-65e-7@gated-at.bofh.it>
On Wed, Jun 7, 2017 at 5:29 PM, Matthew Wilcox <willy@infradead.org> wrote:

> Commit 7dd968163f ("bitmap: bitmap_equal memcmp optimization") was
> rather more restrictive than necessary; we can use memcmp() to implement
> bitmap_equal() as long as the number of bits can be proved to be a
> multiple of 8.  And architectures other than s390 may be able to make
> good use of this optimisation.

> -       if (__builtin_constant_p(nbits) && (nbits % BITS_PER_LONG) == 0)
> +       if (__builtin_constant_p(nbits & 7) && IS_ALIGNED(nbits, 8))
>                 return !memcmp(src1, src2, nbits / 8);

I'm not sure this is a fully correct change.
What exactly ' & 7' part does?
For me looks like you may just drop it.

-- 
With Best Regards,
Andy Shevchenko

[toc] | [next] | [standalone]


#1660694

FromMatthew Wilcox <willy@infradead.org>
Date2017-06-08 05:00 +0200
Message-ID<tPVPX-6Nn-9@gated-at.bofh.it>
In reply to#1660649
On Thu, Jun 08, 2017 at 04:48:04AM +0300, Andy Shevchenko wrote:
> > Commit 7dd968163f ("bitmap: bitmap_equal memcmp optimization") was
> > rather more restrictive than necessary; we can use memcmp() to implement
> > bitmap_equal() as long as the number of bits can be proved to be a
> > multiple of 8.  And architectures other than s390 may be able to make
> > good use of this optimisation.
> 
> > -       if (__builtin_constant_p(nbits) && (nbits % BITS_PER_LONG) == 0)
> > +       if (__builtin_constant_p(nbits & 7) && IS_ALIGNED(nbits, 8))
> >                 return !memcmp(src1, src2, nbits / 8);
> 
> I'm not sure this is a fully correct change.
> What exactly ' & 7' part does?
> For me looks like you may just drop it.

We only need to know if the bottom 3 bits are 0 to apply this optimisation.
For example, if we have a user which does this:

	nbits = 8;
	if (argle)
		nbits += 8;
	if (bitmap_equal(ptr1, ptr2, nbits))
		blah();

then we can use memcmp() because gcc can deduce that the bottom 3 bits
are never set (try it!  it works!).  We don't need nbits as a whole to
be const.

[toc] | [prev] | [next] | [standalone]


#1661130

FromAndy Shevchenko <andy.shevchenko@gmail.com>
Date2017-06-08 14:40 +0200
Message-ID<tQ4Tg-4hK-37@gated-at.bofh.it>
In reply to#1660694
On Thu, Jun 8, 2017 at 5:55 AM, Matthew Wilcox <willy@infradead.org> wrote:
> On Thu, Jun 08, 2017 at 04:48:04AM +0300, Andy Shevchenko wrote:
>> > Commit 7dd968163f ("bitmap: bitmap_equal memcmp optimization") was
>> > rather more restrictive than necessary; we can use memcmp() to implement
>> > bitmap_equal() as long as the number of bits can be proved to be a
>> > multiple of 8.  And architectures other than s390 may be able to make
>> > good use of this optimisation.
>>
>> > -       if (__builtin_constant_p(nbits) && (nbits % BITS_PER_LONG) == 0)
>> > +       if (__builtin_constant_p(nbits & 7) && IS_ALIGNED(nbits, 8))
>> >                 return !memcmp(src1, src2, nbits / 8);
>>
>> I'm not sure this is a fully correct change.
>> What exactly ' & 7' part does?
>> For me looks like you may just drop it.
>
> We only need to know if the bottom 3 bits are 0 to apply this optimisation.
> For example, if we have a user which does this:
>
>         nbits = 8;
>         if (argle)
>                 nbits += 8;
>         if (bitmap_equal(ptr1, ptr2, nbits))
>                 blah();
>
> then we can use memcmp() because gcc can deduce that the bottom 3 bits
> are never set (try it!  it works!).  We don't need nbits as a whole to
> be const.

What I'm talking about is that by my opinion the both below are equivalent.
__builtin_constant_p(nbits)
__builtin_constant_p(nbits & 7)

Thus, again, what & 7 does there?

-- 
With Best Regards,
Andy Shevchenko

[toc] | [prev] | [next] | [standalone]


#1661212

FromRasmus Villemoes <linux@rasmusvillemoes.dk>
Date2017-06-08 15:50 +0200
Message-ID<tQ5YZ-4WL-3@gated-at.bofh.it>
In reply to#1661130
On 8 June 2017 at 14:31, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Jun 8, 2017 at 5:55 AM, Matthew Wilcox <willy@infradead.org> wrote:
>> We only need to know if the bottom 3 bits are 0 to apply this optimisation.
>> For example, if we have a user which does this:
>>
>>         nbits = 8;
>>         if (argle)
>>                 nbits += 8;
>>         if (bitmap_equal(ptr1, ptr2, nbits))
>>                 blah();
>>
>> then we can use memcmp() because gcc can deduce that the bottom 3 bits
>> are never set (try it!  it works!).  We don't need nbits as a whole to
>> be const.
>
> What I'm talking about is that by my opinion the both below are equivalent.
> __builtin_constant_p(nbits)
> __builtin_constant_p(nbits & 7)

They are not. Read Matthew's example again. Assuming that argle is
something non-constant (maybe an argument to the function), the value
of nbits at the time of the bitmap_equal call is _not_ a
compile-time-constant. However, if the compiler is smart (which at
least some versions of gcc are), the compiler may deduce that nbits is
either 8 or 16; there really are no other options. Hence it _is_
statically known that nbits is divisible by 8, so the expression
nbits&7 _is_ compile-time constant (0), so gcc can change the
bitmap_equal call to a memcmp call.

(It may then either pass a run-time value of nbits>>3 and emit a
single memcmp call, or it may decide to unroll the two options,
creating two memcmp calls with 1 and 2 as compile-time arguments;
these may or may not then in turn be "inlined" to code doing roughly
*(u8*)p1 == *(u8*)p2 and similarly for u16 casts).

[toc] | [prev] | [next] | [standalone]


#1661350

FromAndy Shevchenko <andy.shevchenko@gmail.com>
Date2017-06-08 16:50 +0200
Message-ID<tQ6V4-5vT-23@gated-at.bofh.it>
In reply to#1661212
On Thu, Jun 8, 2017 at 4:43 PM, Rasmus Villemoes
<linux@rasmusvillemoes.dk> wrote:
> On 8 June 2017 at 14:31, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>> On Thu, Jun 8, 2017 at 5:55 AM, Matthew Wilcox <willy@infradead.org> wrote:
>>> We only need to know if the bottom 3 bits are 0 to apply this optimisation.
>>> For example, if we have a user which does this:
>>>
>>>         nbits = 8;
>>>         if (argle)
>>>                 nbits += 8;
>>>         if (bitmap_equal(ptr1, ptr2, nbits))
>>>                 blah();
>>>
>>> then we can use memcmp() because gcc can deduce that the bottom 3 bits
>>> are never set (try it!  it works!).  We don't need nbits as a whole to
>>> be const.
>>
>> What I'm talking about is that by my opinion the both below are equivalent.
>> __builtin_constant_p(nbits)
>> __builtin_constant_p(nbits & 7)
>
> They are not. Read Matthew's example again. Assuming that argle is
> something non-constant (maybe an argument to the function), the value
> of nbits at the time of the bitmap_equal call is _not_ a
> compile-time-constant. However, if the compiler is smart (which at
> least some versions of gcc are), the compiler may deduce that nbits is
> either 8 or 16; there really are no other options. Hence it _is_
> statically known that nbits is divisible by 8, so the expression
> nbits&7 _is_ compile-time constant (0), so gcc can change the
> bitmap_equal call to a memcmp call.

Yeah, thanks for detailed explanation.
So, basically what we do, we consider
1. 3 LSBs _is_ constant, *and*
2. They are equal to 0.

> (It may then either pass a run-time value of nbits>>3 and emit a
> single memcmp call, or it may decide to unroll the two options,
> creating two memcmp calls with 1 and 2 as compile-time arguments;
> these may or may not then in turn be "inlined" to code doing roughly
> *(u8*)p1 == *(u8*)p2 and similarly for u16 casts).

-- 
With Best Regards,
Andy Shevchenko

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web