cat > 1.c extern int printf(const char *, ...); extern double pow(double, double); int main(int argc, char **argv) { double d1 = (double) (argc + argv[0][0]); double d2 = pow(d1, 1.0 / 3.0); printf("%f %f\n", d1 * d1, d2); return 0; } ^D $ gcc -O -fno-builtin -ffast-math -fno-lto 1.c /tmp/cc9Il6Md.o:1.c:function main: error: undefined reference to 'pow' [...] $ gcc -O -fno-builtin -ffast-math -flto 1.c /tmp/ccfKmD30.ltrans0.ltrans.o:ccfKmD30.ltrans0.o:function main: error: undefined reference to 'cbrt' [...] R191367 (20120916) - ok, r191654 (20120923) - bug.
-f[no-]builtin-* is a frontend option not supported by LTO (nor by Fortran for example). That it controls also middle-end behavior with respect to LTO streaming 'pow' as a builtin is a bug I suppose (to be analyzed). Probably caused by /* For variables prefer the builtin if one is available. */ else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL) { for (e = first; e; e = e->symbol.next_sharing_asm_name) if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL && DECL_BUILT_IN (e->symbol.decl)) { prevailing = e; break; } } and LTO un-conditionally initializing all builtins (well, and that's needed unless we can do that lazily during streaming as we stream builtin decls by their DECL_FUNCTION_CODE ...). Hm. I'll have a looksee.
Created attachment 29328 [details] patch We do stream things properly as / not as builtin. Only we end up replacing the non-builtin with the prevailing builtin. It seems to me builtins should never "prevail" (we do not touch their cgraph nodes either) but we also should not replace any builtin decl with whatever prevailed (unless maybe there is a visible definition ...?) I have a patch but that causes PR55848 to re-appear (also in this testcase): lto1: error: edge points to wrong declaration:^M <function_decl 0x7fb56f8d2a00 pow^M type <function_type 0x7fb56f8d1e70^M ... Instead of: <function_decl 0x7fb56f7e6f00 __builtin_pow^M type <function_type 0x7fb56f7b60a8^M doesn't happen with -flto-partition=none though. At LTRANs we again see d2_5 = __builtin_pow (d1_3, 3.33333333333333314829616256247390992939472198486328125e-1); d3_6 = __builtin_pow (d1_3, 2.0e+0); which is of course wrong. Something assumes there is only a single prevailing cgraph node per symbol? The callgraph at LTRANS time looks ok to me: pow/2 (pow) @0x7f5806f3ca68 Type: function Visibility: undef external public previous sharing asm name: 3 References: Referring: Read from file: /tmp/ccp4tasf.ltrans0.o Function flags: Called by: main/1 (1.00 per call) Calls: pow/3 (__builtin_pow) @0x7f5806f3c940 Type: function Visibility: external public next sharing asm name: 2 References: Referring: Read from file: /tmp/ccp4tasf.ltrans0.o Function flags: Called by: main/1 (1.00 per call) main/1 (main) @0x7f5806f3c6f0 Type: function Visibility: prevailing_def public References: x.2385/0 (read) Referring: Read from file: /tmp/ccp4tasf.ltrans0.o Function flags: analyzed finalized only_called_at_startup Called by: Calls: abort/4 (0.39 per call) pow/3 (1.00 per call) pow/2 (1.00 per call) but then somehow it's all wrong when reading the call op of the call stmt. The ltrans object fn decl state stream of main has both a builtin and a non-builtin. That's because LTRANS thinks the builtin prevailed. Bah. That's because it happens to come "first" and we skip lto_symtab_merge_decls for LTRANS. Probably ok, but then we also should skip lto_fixup_decls.
Created attachment 29329 [details] alternative patch Patch which disables fixup_decls in LTRANS mode (fixes the testcase). Trying that on LTO bootstrap now ...
Author: rguenth Date: Mon Feb 4 12:19:25 2013 New Revision: 195709 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195709 Log: 2013-02-04 Richard Guenther <rguenther@suse.de> PR lto/56168 * lto-symtab.c (lto_symtab_merge_decls_1): Make non-builtin node prevail as last resort. (lto_symtab_merge_decls): Remove guard on LTRANS here. (lto_symtab_prevailing_decl): Builtins are their own prevailing decl. lto/ * lto.c (read_cgraph_and_symbols): Do not call lto_symtab_merge_decls or lto_fixup_decls at LTRANS time. * gcc.dg/lto/pr56168_0.c: New testcase. * gcc.dg/lto/pr56168_1.c: Likewise. Added: trunk/gcc/testsuite/gcc.dg/lto/pr56168_0.c trunk/gcc/testsuite/gcc.dg/lto/pr56168_1.c Modified: trunk/gcc/ChangeLog trunk/gcc/lto-symtab.c trunk/gcc/lto/ChangeLog trunk/gcc/lto/lto.c trunk/gcc/testsuite/ChangeLog
Fixed.