I'm trying to get __builtin_expect working, but for some reason I can't seem
to figure out what what compiler rev it is supported under, or what I need
to link in (or throw as -fARGS). I also don't seem to have an asm/compiler.h
in any of my compiler packages -- do I need this?
I've tried gcc2.95.2, 2.7.2.3, and egcs-2.91.66, all to no avail - the
linker fails trying to find the symbol, and I can't find it either when
searching static libs with nm.
My test usage is as follows:
int main(int argc, char *argv[])
{
if (__builtin_expect(1,1))
exit(1);
return 0;
}
built simply as "gcc -c test.c -o test"
.. thoughts?
Also, is there a way I can detect (with cpp macros) whether __builtin_expect
is available on a particular platform? I'd like to macro it out on
non-supported versions. My tests show that a simple #ifdef __GNUC__ won't do
the trick. :)
Any information would be greatly appreciated.
Thanks,
Wes
--
Wes Garland
Kingston, ON Canada
Kawasaki EX250-F
/* Do daemons dream of electric sleep()? */
There's no such thing in Gcc, at least according to any of the manuals
I've seen. What gave you the impression it existed? And what's it supposed
to do?
DaveK
--
They laughed at Galileo. They laughed at Copernicus. They laughed at
Columbus. But remember, they also laughed at Bozo the Clown.
"Dave Korn" <no....@my.mailbox.invalid> wrote in message
news:LwD76.43$l%3.7...@newsr1.u-net.net...
(Surely not *the* David Korn?)
> There's no such thing in Gcc, at least according to any of the manuals
> I've seen. What gave you the impression it existed? And what's it supposed
> to do?
From http://gcc.gnu.org/onlinedocs/gcc_5.html#SEC113:
-- 8< -- 8< -- 8< --
__builtin_expect(exp, c)
You may use __builtin_expect to provide the compiler with branch prediction
information. In general, you should prefer to use actual profile feedback
for this (`-fprofile-arcs'), as programmers are notoriously bad at
predicting how their programs actually perform. However, there are
applications in which this data is hard to collect. The return value is the
value of exp, which should be an integral expression. The value of c must be
a compile-time constant. The semantics of the builtin are that it is
expected that exp == c. For example:
if (__builtin_expect (x, 0))
foo ();
would indicate that we do not expect to call foo, since we expect x to be
zero. Since you are limited to integral expressions for exp, you should use
constructions such as
if (__builtin_expect (ptr != NULL, 1))
error ();
when testing pointer or floating-point values.
-- 8< -- 8< -- 8< --
Thoughts? I still haven't figured out how to get code containing references
to this function to compile.
Thanks,
Wes
Yes, I am indeed *the* David Korn. Not the AT&T unix shell guy; he's just
*a* David Korn. Of course if you were to ask him, he might tell you the
same thing in reverse...
>> There's no such thing in Gcc, at least according to any of the manuals
>> I've seen. What gave you the impression it existed? And what's it
supposed
>> to do?
>
>From http://gcc.gnu.org/onlinedocs/gcc_5.html#SEC113:
Aha. There's no sign of it at
http://gcc.gnu.org/onlinedocs/gcc-2.95.2/gcc_4.html#SEC61 so I think it's a
new feature in the currently-under-development Gcc V3.
>Thoughts? I still haven't figured out how to get code containing references
>to this function to compile.
You'd have to download the latest Gcc sources from the CVS and build them.
However V3 is still unstable and under development, so that's not really
what you want to do if you need a reliable production-quality compiler,
although it works quite well on most platforms. Perhaps your best bet is to
wait until V3 is released to start using this feature.
[from your original posting]
>Also, is there a way I can detect (with cpp macros) whether
__builtin_expect
>is available on a particular platform? I'd like to macro it out on
>non-supported versions. My tests show that a simple #ifdef __GNUC__ won't
do
>the trick. :)
It will actually, but only if you know that __GNUC__ isn't just #def'd,
but is #def'd to equal the numeric value of the compiler major revision
number. So you'd really want to test
#if __GNUC__ >= 3
... builtin_expect is available...
#else
... builtin_expect is not available...
#endif
cheers,
> Yes, I am indeed *the* David Korn. Not the AT&T unix shell guy; he's
just
> *a* David Korn. Of course if you were to ask him, he might tell you the
> same thing in reverse...
LOL -- good answer. ;-)
> >> There's no such thing in Gcc, at least according to any of the
manuals
> http://gcc.gnu.org/onlinedocs/gcc-2.95.2/gcc_4.html#SEC61 so I think it's
a
> new feature in the currently-under-development Gcc V3.
Ah -- that makes perfect sense. I hadn't realized that the documentation I
was reading was for the current development stream instead of the latest
stable build -- it never crossed my mind that any docs would be that
up-to-date: good job, gcc crew!
OTOH, if I had RTFWP more carefully I would noticed that. :-)
> You'd have to download the latest Gcc sources from the CVS and build
them.
> However V3 is still unstable and under development, so that's not really
> what you want to do if you need a reliable production-quality compiler,
> although it works quite well on most platforms. Perhaps your best bet is
to
> wait until V3 is released to start using this feature.
Right on -- I'm sure that won't be more than a few months down the road. I'm
a patient coder. :-)
> It will actually, but only if you know that __GNUC__ isn't just #def'd,
> but is #def'd to equal the numeric value of the compiler major revision
> number. So you'd really want to test
>
> #if __GNUC__ >= 3
> ... builtin_expect is available...
> #else
> ... builtin_expect is not available...
> #endif
Perfectomundo. I hadn't realized that yet, either, although it makes perfect
sense. Do you by any chance know of any macros which can be used to test
revisions of the compiler? (Not that I can think of a reason I'd need
to..).. I'm asking because IIRC the cpp won't do floating point comparisions
in an #if.
So, this is good news. I can use
#if !defined(__GNUC_) || (__GNUC__ < 3)
# define __builtin_expect(a,b) (a)
#endif
in current development code fairly safely, and see what happens when I
upgrade to gcc v3.
I'm actually quite interested in seeing what would happen in code like:
if (__builtin_expect(mytest(a,b,c), 1))
where mytest(a,b,c) is very expensive __pure__ function that evaluates to 1
in almost all cases. FRS, I mostly Ultrasparc II MP platforms.
[ Of course, I have better uses for __builtin_expect, but that's another
story ].
Thanks for the insight!
Cheers,
Wes
<wha....oww> Careful, you made me jump!
>> It will actually, but only if you know that __GNUC__ isn't just #def'd,
>> but is #def'd to equal the numeric value of the compiler major revision
>> number. So you'd really want to test
>>
>> #if __GNUC__ >= 3
>> ... builtin_expect is available...
>> #else
>> ... builtin_expect is not available...
>> #endif
>
>Perfectomundo. I hadn't realized that yet, either, although it makes
perfect
>sense. Do you by any chance know of any macros which can be used to test
>revisions of the compiler? (Not that I can think of a reason I'd need
>to..).. I'm asking because IIRC the cpp won't do floating point
comparisions
>in an #if.
I don't think anything's expressed as a FP #define, there's another macro
called __GNUC_MINOR__. So to test for the latest release of the compiler,
you'd say
#if (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
I don't know any way to distinguish between say 2.95.1 and 2.95.2. Also,
you can save testing whether or not these macros are defined by taking
advantage of the fact that any undefined macro defaults to a value of zero
in numerical comparisons.
>I'm actually quite interested in seeing what would happen in code like:
>
>if (__builtin_expect(mytest(a,b,c), 1))
>
>where mytest(a,b,c) is very expensive __pure__ function that evaluates to 1
>in almost all cases. FRS, I mostly Ultrasparc II MP platforms.
If mytest is very expensive, surely the overhead from it will render
useless any minor saving of a few clock cycles that branch prediction can
get you?
Oops. Sorry, eh? ;-)
> #if (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
Ah. Excellent. :)
> >I'm actually quite interested in seeing what would happen in code like:
> >
> >if (__builtin_expect(mytest(a,b,c), 1))
> >
> >where mytest(a,b,c) is very expensive __pure__ function that evaluates to
1
> >in almost all cases. FRS, I mostly Ultrasparc II MP platforms.
>
> If mytest is very expensive, surely the overhead from it will render
> useless any minor saving of a few clock cycles that branch prediction can
> get you?
Well, since the function is declared as pure (it does not modify its input
parameters, and is deterministic albeit expensive), I'm curious as to what
sort of savings I can get by branch-predicting its output, and then letting
the pure "optimization" (presumably some kind of register-based results
cache?) run its course naturally in the other CPU pipeline.
I suspect that I'll actually wind up slowing things down (the real world
never seems to match intuitive guesses, when you're talking compiler
optimizations), but I'm curious as to how those two optimizations will
interact with one another.
Another desire for the branch-prediction code was in this sort of problem:
void hello()
{
static int i=0;
if (__builtin_expect((i==0), 0)
{
i = 1;
do_stuff();
}
world();
}
...of course, the good folks on the GCC team may very well have addressed
that particular construct in the past without needing programmer input about
it. I'd hazard a guess [not knowing much about gcc specifically] that that
would be a relatively easy catch at the RTL-level with a peephole optimizer
that understands branch prediction for my CPU. But, I'm a programmer, I'm
curious, hell-bent on saving every cycle I can, and I know how to use a
profiler. So it's unlikely that I'll wind up with sub-optimal code as an end
product, even if that means letting the compiler do all the optimization for
me.
Cheers,
Wes