Discussion:
[x264-devel] configure: test for log2f fails, external reference folded out
Dirk Fieldhouse
2018-10-10 11:16:22 UTC
Permalink
I'm building the 8 October stable version on a MIPS Broadcom 7405 SoC
platform with gcc-4.5.2 and uClibc-0.9.29.

The test at configure l1070 for support of log2f() in libm
(here:<http://git.videolan.org/?p=x264.git;a=blob;f=configure;h=07ba4490f4be6699549c8ac2f2745a0512ccea77;hb=HEAD#l1070>)
succeeds incorrectly.

The program fragment used by configure's cc_check call is

#include <math.h>

int main(void) {

log2f(2);

return 0;
}

gcc 4.5.2 folds the constant expression log2f(2) leaving no external
reference to log2f. It even does this with no optimisation set.
Consequently the build defines HAVE_LOG2F to 1 when in fact there is no
log2f() in the libm provided by this version of uClibc.

Whereas this reference survives:

#include <math.h>

int main(void) {

float x = 2; x = log2f(x);

return 0;
}

I suppose that even this is not guaranteed by the C standard(s) to
survive compile-time evaluation, but it beats this version of gcc.

To implement this, replace configure l1070 by this line

if cc_check 'math.h' '' 'float x = 2; x = log2f(x);' ; then

I'm not subscribed to the list at the moment so please CC: me as well.

thx
/df
--
London SW6
UK
BugMaster
2018-10-15 18:55:45 UTC
Permalink
Post by Dirk Fieldhouse
I'm building the 8 October stable version on a MIPS Broadcom 7405 SoC
platform with gcc-4.5.2 and uClibc-0.9.29.
The test at configure l1070 for support of log2f() in libm
(here:<http://git.videolan.org/?p=x264.git;a=blob;f=configure;h=07ba4490f4be6699549c8ac2f2745a0512ccea77;hb=HEAD#l1070>)
succeeds incorrectly.
The program fragment used by configure's cc_check call is
#include <math.h>
int main(void) {
log2f(2);
return 0;
}
gcc 4.5.2 folds the constant expression log2f(2) leaving no external
reference to log2f. It even does this with no optimisation set.
Consequently the build defines HAVE_LOG2F to 1 when in fact there is no
log2f() in the libm provided by this version of uClibc.
#include <math.h>
int main(void) {
float x = 2; x = log2f(x);
return 0;
}
I suppose that even this is not guaranteed by the C standard(s) to
survive compile-time evaluation, but it beats this version of gcc.
To implement this, replace configure l1070 by this line
if cc_check 'math.h' '' 'float x = 2; x = log2f(x);' ; then
I'm not subscribed to the list at the moment so please CC: me as well.
thx
/df
Hi.

So log2f exists at compile time for constant evolution but not at
runtime for variables? It is weird system/environment. Or is this only
due use of uClibc instead of glibc (and gcc still use glibc during
constant evolution)?

Anyway for even more obstacle to compiler to optimize it out we can
also add volatile to variable declaration.

Check that it works as expected with attached patch.
BugMaster
2018-10-16 06:04:21 UTC
Permalink
Post by BugMaster
...
So log2f exists at compile time for constant evolution but not at
runtime for variables? It is weird system/environment. Or is this only
due use of uClibc instead of glibc (and gcc still use glibc during
constant evolution)?
Exactly. This uClibc's libmath doesn't have log2f(), but perhaps this
gcc was built with the equivalent of HAVE_LOGF=0, causing its internal
log2f() to be defined through logf(). Or perhaps it does enough static
analysis to determine that log2f(2) is never used and so discards it. Or
both?
Post by BugMaster
Anyway for even more obstacle to compiler to optimize it out we can
also add volatile to variable declaration.
Check that it works as expected with attached patch.
Supporting the 2nd hypothesis above, it's not enough just to mention
log2f(x). You actually have to assign it as in my original proposal
above, so the proposed patch doesn't quite work even with the "volatile"
qualifier. I've made the trivial mod in the attached.
regards
/df
Hm. So use of function result is obligatory condition to not remove it
call? And what about simple 'return log2f(2);' (attached patch)?
Or would it replace it with constant?
Dirk Fieldhouse
2018-10-16 09:04:40 UTC
Permalink
Post by BugMaster
Post by BugMaster
...
So log2f exists at compile time for constant evolution but not at
runtime for variables? It is weird system/environment. Or is this only
due use of uClibc instead of glibc (and gcc still use glibc during
constant evolution)?
Exactly. This uClibc's libmath doesn't have log2f(), but perhaps this
gcc was built with the equivalent of HAVE_LOGF=0, causing its internal
log2f() to be defined through logf(). Or perhaps it does enough static
analysis to determine that log2f(2) is never used and so discards it. Or
both?
Obvs I meant libm above, not libmath.
Post by BugMaster
Post by BugMaster
Anyway for even more obstacle to compiler to optimize it out we can
also add volatile to variable declaration.
Check that it works as expected with attached patch.
Supporting the 2nd hypothesis above, it's not enough just to mention
log2f(x). You actually have to assign it as in my original proposal
above, so the proposed patch doesn't quite work even with the "volatile"
qualifier. I've made the trivial mod in the attached.
Hm. So use of function result is obligatory condition to not remove it
call? And what about simple 'return log2f(2);' (attached patch)?
Or would it replace it with constant?
It would and does. Maybe it's just ambitious constant folding after all.

This fragment does correctly detects the lack of log2f() in libm --
maybe it's the simplest to do so:

volatile float x = 2; return log2f(x);

According to man gcc, the option -frounding-math "disables constant
folding of floating-point expressions at compile time", but this option
doesn't make the fragment 'return log2f(2);' work. It does however make
'return log2f(X);' where X is a float constant other than 2, work; so
gcc knows that logn(n)==1 even without folding.

regards
/df
--
London SW6
UK
Loading...