Bug 16223

Summary: Wrong-code due to more inlining
Product: gcc Reporter: Erik <gcc-erikd>
Component: rtl-optimizationAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: gcc-bugs
Priority: P2 Keywords: wrong-code
Version: 3.4.0   
Target Milestone: ---   
Host: i686-pc-linux-gnu Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu Known to work: 4.0.0
Known to fail: 3.4.0 3.3.3 3.2.3 3.0.4 Last reconfirmed:
Attachments: Preprocessor output of the code wich fails when compiled with gcc-3.4.0

Description Erik 2004-06-27 04:28:57 UTC
*  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
Comment 1 Erik 2004-06-27 04:31:39 UTC
Created attachment 6634 [details]
Preprocessor output of the code wich fails when compiled with gcc-3.4.0
Comment 2 Erik 2004-06-27 04:57:26 UTC
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.
Comment 3 Andrew Pinski 2004-06-27 08:37:41 UTC
I should note that unit-at-a-time is just inlining static functions, Note I can reproduce it with -O1 
-finline-functions.
Comment 4 Serge Belyshev 2004-06-27 11:18:17 UTC
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.
Comment 5 Andrew Pinski 2004-06-27 17:59:16 UTC
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.
Comment 6 Serge Belyshev 2004-06-27 19:33:23 UTC
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.
Comment 7 Andrew Pinski 2004-06-27 19:46:19 UTC
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 ***