Broken Compiler Optimizations

From RockWiki

Jump to: navigation, search

Broken Compiler Optimizations

Some GCC compiler versions produce buggy output when certain optimization options are enabled. Generally speaking, whether a bug appears or not depends on the source files that are compiled, the GCC version and the type of optimization used.

It is safest to avoid combinations of GCC versions and optimizations which are known to be broken. While such known bugs usually become apparent in one certain part of one program, they may actually appear in many more places, causing subtle errors.

A complete and up to date database of all known and reported GCC compiler bugs (including broken optimizations) is available at the GCC Bugzilla.

This page can be used to gather information on broken compiler optimizations that have not yet been reported to GCC Bugzilla. It aims towards providing all required information for reporting compiler optimization bugs.

It is important to discern broken compiler optimizations from other bugs, e.g. in hardware, other software, or software you want to compile.

A bug is caused by broken compiler optimizations if the appearance of the bug depends on optimization options and the source code is valid. E.g. a program, compiled with gcc 4.0.2, optimized for Pentium MMX CPUs, works as expected while the same program optimized for Athlon XP is buggy. If the source code of the program included assembly code optimized for different CPUs, the bug might as well be in the assembly code.

So if you want to know where those segmentation faults and core dumps in your program come from, try to compile the program with different optimizations. If the program works with one, but not with the other, then you have probably found a broken compiler optimization!

If you want to help get this bug fixed, there's a standard procedure that makes things a lot easier for a lot of people. It is described at GCC Bugs. Please follow these rules whenever reporting a bug to GCC Bugzilla. Parts relevant to this page are mentioned below.

First of all, check if the bug is already filed at the GCC Bugzilla search page. If there is no entry or only one without a test case to reproduce the bug, read on.

To quote GCC Bugs: "The main purpose of a bug report is to enable us to fix the bug. The most important prerequisite for this is that the report must be complete and self-contained."

Therefore the following items should be regarded as mandatory for every bug report:

  • the exact version of GCC, the system type, and the options given when GCC was configured/built: these can be obtained from the output of LC_ALL=C gcc -v. If possible, try a recent development snapshot of GCC (gcc41 package).
  • the complete command line that triggers the bug: this refers to the options passed to gcc for compilation, especially optimization options in our case. The exact command line used cannot be found in the build log but in the cmd_wrapper.log.
  • the compiler output (error messages, warnings, etc.): can be found in the build logs.
  • the preprocessed file (*.i*) that triggers the bug, generated by adding -save-temps to the complete compilation command: if the bug appears at compile time, usually as an ICE (Internal Compiler Error), re-execute the last compilation command with -save-temps added. The resulting preprocessed file can be used as a complete and self-contained testcase.

For run time bugs, the source code that triggers the bug has to be reduced to a single file. To quote: "The only excuses to not send us the preprocessed sources are (i) if you've found a bug in the preprocessor, (ii) if you've reduced the testcase to a small file that doesn't include any other file or (iii) if the bug appears only when using precompiled headers."

bc 1.06

  •  !GCC version, configure options and system type:
sh-2.05b# gcc -v
Reading specs from /usr/lib/gcc/i686-unknown-linux-gnu/4.0.2/specs
Target: i686-unknown-linux-gnu
Configured with: ../configure --prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin
--libdir=/usr/lib --datadir=/usr/share --includedir=/usr/include 
--infodir=/usr/share/info --mandir=/usr/share/man --sysconfdir=/etc 
--localstatedir=/var --disable-debug --disable-nls --without-libpam 
--without-pam --disable-libpam --disable-pam --build=i686-unknown-linux-gnu 
--host=i686-unknown-linux-gnu --disable-multilib --enable-languages=c,c++,objc,f95 
--enable-__cxa_atexit --enable-shared=yes --with-gnu-as 
--enable-version-specific-runtime-libs --with-gnu-ld --enable-threads=posix
Thread model: posix
gcc version 4.0.2
  • the complete command line that triggers the bug:
    • Rock Development Tree Rev. 6630, with SubMaster patches no.
      • 20050912074921161
      • 2005101310203927182
      • 2005101819081924835
      • 2005111513084518228
      • 2005111513084518228
      • 2005102104553617243
      • 2005102609174110254
    • Full build with the following user config file:
ROCKCFGUSR_ABORT_ON_ERROR='0'
ROCKCFGUSR_EXPERT='1'
ROCKCFGUSR_PKGFILE_VER='0'
ROCKCFGUSR_PKG_GCC_GCC34='0'
ROCKCFGUSR_PKG_GCC_GCC40='1'
ROCKCFGUSR_RETRY_BROKEN='0'
ROCKCFGUSR_SRC_TMPFS='1'
ROCKCFGUSR_TARGET='bootdisk'
ROCKCFGUSR_VERBOSE='1'
ROCKCFGUSR_X86_OPT='athlon-xp'
    • Using the so-created bc binary reveals a bug:
sh-2.05b# echo x=1 | bc -l
Segmentation fault (core dumped)
  • the compiler output (error messages, warnings, etc.): gcc 4.0.2 issues some warnings:
number.c:978: warning: incompatible implicit declaration of built-in function 'memset'
number.c:979: warning: incompatible implicit declaration of built-in function 'memcpy'
number.c:1442: warning: incompatible implicit declaration of built-in function 'strlen'
  • the preprocessed file (*.i*) that triggers the bug: none yet
  • additional notes:
    • Corresponding entry in !GCC Bugzilla: none found
    • This bug appears with gcc 4.0.2 regardless of the CPU optimization options used (tested with ROCKCFGUSR_X86_OPT set to 'none', 'pentium-mmx' and 'athlon-xp'). The working version of bc was compiled with gcc 3.4.4, optimized for pentium-mmx.