From: "H. Peter Anvin" <hpa@zytor.com>
To: "Robert P. J. Day" <rpjday@mindspring.com>
Cc: Vegard Nossum <vegard.nossum@gmail.com>, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] Optimize is_power_of_2().
Date: Fri, 15 Jun 2007 13:26:07 -0700 [thread overview]
Message-ID: <4672F5DF.7070506@zytor.com> (raw)
In-Reply-To: <Pine.LNX.4.64.0706151427370.12949@localhost.localdomain>
Robert P. J. Day wrote:
> On Fri, 15 Jun 2007, H. Peter Anvin wrote:
>
>> Vegard Nossum wrote:
>>> From: Vegard Nossum <vegard@peltkore.net>
>>> Date: Fri, 15 Jun 2007 18:35:49 +0200
>>> Subject: [PATCH] Optimize is_power_of_2().
>>>
>>> Rationale: Removes one conditional branch and reduces icache
>>> footprint. Proof: If n is false, the product of n and any value is
>>> false. If n is true, the truth of (n * x) is the truth of x.
>> You realize that on a lot of platforms, multiplication is done by an
>> out-of-line subroutine, and that even on those that aren't, it's
>> generally a long-pipeline operation, right?
>
> i was *just* about to mention somthing of the sort, but probably not
> as succinctly.
>
You also realize, I hope, that obfuscating this for the compiler just
hurts. As has already been described, there are versions involving
jumps, selects, multiplication, tables, ffs, and popcount. All of those
operations are hideously expensive on some architectures and cheap on
others.
Personally, I would bet that the version as originally written is
probably best, since select (conditional move) is a fairly commonly
supported operation, especially on architectures where jumps are expensive.
Just to confuse the situation further, here is yet another version:
bool is_power_of_2(unsigned long n)
{
return !!n & !(n & (n-1));
}
... which, on i686 compiles to:
00000000 <is_power_of_2>:
0: 85 c0 test %eax,%eax
2: 8d 50 ff lea 0xffffffff(%eax),%edx
5: 0f 95 c1 setne %cl
8: 85 d0 test %edx,%eax
a: 0f 94 c0 sete %al
d: 0f b6 c0 movzbl %al,%eax
10: 21 c8 and %ecx,%eax
12: c3 ret
In the current version, gcc does generate a jump on i686 and x86-64:
00000000 <is_power_of_2>:
0: 89 c2 mov %eax,%edx
2: 31 c0 xor %eax,%eax
4: 85 d2 test %edx,%edx
6: 74 0b je 13 <is_power_of_2+0x13>
8: 8d 42 ff lea 0xffffffff(%edx),%eax
b: 85 c2 test %eax,%edx
d: 0f 94 c0 sete %al
10: 83 e0 01 and $0x1,%eax
13: f3 c3 repz ret
-hpa
next prev parent reply other threads:[~2007-06-15 20:26 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-15 16:56 [PATCH] Optimize is_power_of_2() Vegard Nossum
2007-06-15 18:21 ` H. Peter Anvin
2007-06-15 18:28 ` Robert P. J. Day
2007-06-15 20:26 ` H. Peter Anvin [this message]
2007-06-15 19:47 ` Jan Engelhardt
2007-06-15 19:54 ` David M. Lloyd
2007-06-15 19:57 ` David M. Lloyd
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4672F5DF.7070506@zytor.com \
--to=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rpjday@mindspring.com \
--cc=vegard.nossum@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox