* the exact version of GCC; gcc-3.4.0 downloaded from GNU ftp site. Same symptom also present in gcc version 3.4.1 20040625. * the system type; Native i686-pc-linux-gnu * the options given when GCC was configured/built; ../src/configure -v --enable-languages=c --prefix=/home/erikd/Local --program-prefix=test-3.4.0- * the complete command line that triggers the bug; test-3.4.0-gcc -v -save-temps -g -O2 -W -Wall -Werror term_test.c -lm -o term_test-3.4 * the compiler output (error messages, warnings, etc.); and Reading specs from /home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0/specs Configured with: ../src/configure -v --enable-languages=c --prefix=/home/erikd/Local --program-prefix=test- : (reconfigured) ../src/configure -v --enable-languages=c --prefix=/home/erikd/Local --program-prefix=test-3.4.0- Thread model: posix gcc version 3.4.0 /home/erikd/Local/libexec/gcc/i686-pc-linux-gnu/3.4.0/cc1 -E -quiet -v term_test.c -mtune=pentiumpro -W -Wall -Werror -fworking-directory -O2 -o term_test.i ignoring nonexistent directory "/home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../i686-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /home/erikd/Local/include /home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0/include /usr/include End of search list. /home/erikd/Local/libexec/gcc/i686-pc-linux-gnu/3.4.0/cc1 -fpreprocessed term_test.i -quiet -dumpbase term_test.c -mtune=pentiumpro -auxbase term_test -g -O2 -W -Wall -Werror -version -o term_test.s GNU C version 3.4.0 (i686-pc-linux-gnu) compiled by GNU C version 3.3.4 (Debian). GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 as --traditional-format -V -Qy -o term_test.o term_test.s GNU assembler version 2.14.90.0.7 (i386-linux) using BFD version 2.14.90.0.7 20031029 Debian GNU/Linux /home/erikd/Local/libexec/gcc/i686-pc-linux-gnu/3.4.0/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o term_test-3.4 /usr/lib/crt1.o /usr/lib/crti.o /home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0/crtbegin.o -L/home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0 -L/home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0/../../.. term_test.o -lm -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /home/erikd/Local/lib/gcc/i686-pc-linux-gnu/3.4.0/crtend.o /usr/lib/crtn.o * the preprocessed file (*.i*) that triggers the bug, generated by adding -save-temps to the complete compilation command, or, in the case of a bug report for the GNAT front end, a complete set of source files (see below). Will attempt to attach the pre-processor output to the bug. Bug Description --------------- The code is a stripped down version of a test case which is part of the test suite for a library I am the author of. In successful completion, the program should print out: term_test : pass term_test : pass and when it fails it prints out: term_test : Line 152 : Bad output frame count. terminate : 10 src_ratio : 0.1000 input_len : 1848 input_len * src_ratio : 184.800000 output_frames_gen : 214 The code passes for gcc-3.3 and earlier, but fails when compiled with gcc-3.4. The compiler produces no warnings or errors when generating the executable that fails. I have looked at the docs here: http://gcc.gnu.org/gcc-3.4/changes.html which suggests using the -fno-unit-at-a-time switch. This fixes the problem, but I don't think this compiler switch should be necessary because my code: 0) doesn't use any assembler 1) doesn't have any unreferenced static data 2) has only one static (inline) function which is only called from C
Created attachment 6634 [details] Preprocessor output of the code wich fails when compiled with gcc-3.4.0
Interesting extra data. In the function calc_output in the preprocessor file term_test.i : inline double calc_output (float * buffer) { double fraction, left, right, icoeff ; int f_index, increment = 3 ; f_index = 2 * increment + 2 ; left = right = 0.0 ; do { fraction = f_index / 2.0 ; icoeff = coeffs [0] + fraction * coeffs [1] ; left += icoeff * buffer [0] ; f_index -= increment ; } while (f_index >= 0) ; return (left + right) ; } Its pretty obvious that the variable right contains 0.0 at the return statement. If the return statment just returns left instead of left + right, the test case passes. This is probably the strongest evidence that something is really screwy.
I should note that unit-at-a-time is just inlining static functions, Note I can reproduce it with -O1 -finline-functions.
There are bugs in your code: input_index += 1.0 / src_ratio ; filter->b_current = (filter->b_current + lrint (floor (input_index))) % filter->b_len ; ^^^^^ this should be 'round' input_index -= floor (input_index) ; ^^^^^ same here. Suppose src_ratio = 0.1 then floor (1.0 / src_ratio) can be either 9.0 or 10.0 depending on internal precision.
Reopening for now, I will note that it fails on 3.3.3, 3.2.3, and 3.0.4 with -O1 -finline-functions also so this is not a regression at all, just more inlining causes something else to happen.
Tescase uses floor() written in inline assembly, so 'inlining problem' is basically lacking of rounding argument to floor() from 80 (long double, precision of x86 fp registers) to 64 bits (plain double) when floor() gets inlined. This is why floor(1.0/src_ratio) magically becomes 9.0 when src_ratio = 0.1 but you expected 10.0. Keep in mind that 0.1 and other 'round' values cannot be represented exactly in binary form. So result of (1.0/0.1) depends on rounding mode. Insert "printf ("%i \n", filter->b_current);" at end of loop in sinc_process () and see what happens when you compile this with different options/different compilers. Testcase is wrong. wrong. wrong.
So this is just the case of excussive precission, aka PR 323 and nothing else. *** This bug has been marked as a duplicate of 323 ***