[Bug 1169156] New: GCC9 wrong handling of builtin_constant_p()
http://bugzilla.suse.com/show_bug.cgi?id=1169156 Bug ID: 1169156 Summary: GCC9 wrong handling of builtin_constant_p() Classification: openSUSE Product: openSUSE Distribution Version: Leap 15.2 Hardware: Other OS: Other Status: NEW Severity: Normal Priority: P5 - None Component: Development Assignee: matz@suse.com Reporter: ptesarik@suse.com QA Contact: qa-bugs@suse.de CC: msuchanek@suse.com, nborisov@suse.com, tiwai@suse.com Found By: --- Blocker: --- Created attachment 835407 --> http://bugzilla.suse.com/attachment.cgi?id=835407&action=edit Reproducer GCC9 does not handle builtin_constant_p() correctly in some cases. The offending statement is this: buf->f_bavail = div_u64(total_free_data, factor); However, factor is not a build-time constant. It is initialized to 1, but it may be later set to the result of an extern function call (i.e. GCC cannot make any assumptions about its return value). IIUC GCC does not know with any certainty whether the value is constant, or not, so it generates code for both cases. The code is originally taken from the Linux kernel sources, fails because of unresolved references to __aeabi_uldivmod. I have trimmed it down and made it self-contained. It is not (yet) a minimal reproducer, but getting close. Build it with a 32-bit ARM compiler (native or cross-compiler) like this: $ gcc-9 -nostdinc -std=gnu89 -marm -march=armv7-a -O2 -c gcc9-arm-div.c -o gcc9-arm-div.o I used native gcc-9 from openSUSE:Leap:15.2:ARM to verify the bug: $ gcc-9 -v Using built-in specs. COLLECT_GCC=gcc-9 COLLECT_LTO_WRAPPER=/usr/lib/gcc/armv7hl-suse-linux-gnueabi/9/lto-wrapper Target: armv7hl-suse-linux-gnueabi Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --libexecdir=/usr/lib --enable-languages=c,c++,fortran,go --disable-werror --with-gxx-include-dir=/usr/include/c++/9 --enable-ssp --disable-libssp --disable-libvtv --disable-cet --disable-libcc1 --disable-plugin --with-bugurl=https://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --with-slibdir=/lib --with-system-zlib --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --with-gcc-major-version-only --enable-linker-build-id --enable-linux-futex --enable-gnu-indirect-function --program-suffix=-9 --without-system-libunwind --with-arch=armv7-a --with-tune=cortex-a15 --with-float=hard --with-abi=aapcs-linux --with-fpu=vfpv3-d16 --disable-sjlj-exceptions --build=armv7hl-suse-linux-gnueabi --host=armv7hl-suse-linux-gnueabi Thread model: posix gcc version 9.2.1 20190820 [gcc-9-branch revision 274748] (SUSE Linux) It can also be reproduced with a cross-compiler. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c1
--- Comment #1 from Petr Tesařík
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c2
--- Comment #2 from Petr Tesařík
*** Bug 1169132 has been marked as a duplicate of this bug. ***
If you want to see the original sources, they are attached to that bug. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c3
--- Comment #3 from Richard Biener
http://bugzilla.suse.com/show_bug.cgi?id=1169156
Lubos Kocman
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c4
--- Comment #4 from Petr Tesařík
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c5
--- Comment #5 from Petr Tesařík
You may also use '__builtin_constant_p' in initializers for static data. For instance, you can write
static const int table[] = { __builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1, /* ... */ };
This is an acceptable initializer even if EXPRESSION is not a constant expression, including the case where '__builtin_constant_p' returns 1 because EXPRESSION can be folded to a constant but EXPRESSION contains operands that are not otherwise permitted in a static initializer (for example, '0 && foo ()'). GCC must be more conservative about evaluating the built-in in this case, because it has no opportunity to perform optimization.
So, I beg to treat the current GCC9 behaviour as a bug. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c6
Richard Biener
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c7
--- Comment #7 from Petr Tesařík
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c8
--- Comment #8 from Richard Biener
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c9
--- Comment #9 from Petr Tesařík
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c10
--- Comment #10 from Michael Matz
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c11
--- Comment #11 from Petr Tesařík
[...] (I will note that the problem for the kernel here is non trivial: even if they were to provide an implementation of the division function of libgcc.a, it would then indeed be called at runtime, and the whole point was to not have to do the expensive division)
I tend to agree. It has never been clear to me why the kernel re-invents the wheel. GCC is certainly clever enough to replace a divide-by-constant with a multiply-by-reciprocal. There might have been some ancient GCC versions which could not do that, but I doubt they are used to build the kernel by anyone. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c12
--- Comment #12 from Michal Suchanek
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c13
--- Comment #13 from Petr Tesařík
Still it's done for 32bit division anyway so all this does already happen.
As a matter of fact, it's even done for 64-bit division. If none of the shortcuts can be taken, do_div() does this: __rem = __div64_32(&(n), __base); Now, __div64_32() on arm is implemented in inline assembly as: "bl __do_div64" The rest of the function merely makes sure that input/output registers are assigned correctly. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c14
--- Comment #14 from Richard Biener
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c15
Petr Tesařík
Note we may not have special optimized 64bit / 32bit division handling.
Bummer. Shall I file a feature request for a future GCC version? -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.suse.com/show_bug.cgi?id=1169156
http://bugzilla.suse.com/show_bug.cgi?id=1169156#c16
Richard Biener
(In reply to Richard Biener from comment #14)
Note we may not have special optimized 64bit / 32bit division handling.
Bummer.
Shall I file a feature request for a future GCC version?
I can handle that for upstream (a SUSE bugzilla isn't helpful). But it would need details on what can be optimized [on specific targets], for example with testcases with specific (non-)constants. -- You are receiving this mail because: You are on the CC list for the bug.
participants (1)
-
bugzilla_noreply@novell.com