Summary: | Wrong-code due to more inlining | ||
---|---|---|---|
Product: | gcc | Reporter: | Erik <gcc-erikd> |
Component: | rtl-optimization | Assignee: | 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
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. |