This removes streaming of cl_target_option (we can't stream pointers in it). The info was redundant given that we do stream the target attribute itself. So the following patch re-builds DECL_FUNCTION_SPECIFIC_TARGET at tree loading time (we need it during WPA inline analysis as well).
LTO bootstrapped and tested on x86_64-unknown-linux-gnu, ok? (and yes, this fixes the libcpp/lex.o miscompare I was seeing with LTO bootstrap) The target hook implementations never use the 'name' or 'flags' arguments so I wonder if we should change its signature. That makes the values I pass to those args less arbitrary ;) Thanks, Richard. 2014-02-14 Richard Biener <rguent...@suse.de> PR lto/60179 * lto-streamer-out.c (DFS_write_tree_body): Do not follow DECL_FUNCTION_SPECIFIC_TARGET. (hash_tree): Do not hash DECL_FUNCTION_SPECIFIC_TARGET. * tree-streamer-out.c (pack_ts_target_option): Remove. (streamer_pack_tree_bitfields): Do not stream TS_TARGET_OPTION. (write_ts_function_decl_tree_pointers): Do not stream DECL_FUNCTION_SPECIFIC_TARGET. * tree-streamer-in.c (unpack_ts_target_option): Remove. (unpack_value_fields): Do not stream TS_TARGET_OPTION. (lto_input_ts_function_decl_tree_pointers): Do not stream DECL_FUNCTION_SPECIFIC_TARGET. lto/ * lto.c (compare_tree_sccs_1): Do not compare DECL_FUNCTION_SPECIFIC_TARGET. (lto_read_decls): Re-build DECL_FUNCTION_SPECIFIC_TARGET. Index: gcc/lto-streamer-out.c =================================================================== *** gcc/lto-streamer-out.c (revision 207756) --- gcc/lto-streamer-out.c (working copy) *************** DFS_write_tree_body (struct output_block *** 550,556 **** if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) { DFS_follow_tree_edge (DECL_FUNCTION_PERSONALITY (expr)); ! DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_TARGET (expr)); DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr)); } --- 550,556 ---- if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) { DFS_follow_tree_edge (DECL_FUNCTION_PERSONALITY (expr)); ! /* Do not DECL_FUNCTION_SPECIFIC_TARGET. They will be regenerated. */ DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr)); } *************** hash_tree (struct streamer_tree_cache_d *** 885,891 **** strlen (TRANSLATION_UNIT_LANGUAGE (t)), v); if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! v = iterative_hash (t, sizeof (struct cl_target_option), v); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) v = iterative_hash (t, sizeof (struct cl_optimization), v); --- 885,891 ---- strlen (TRANSLATION_UNIT_LANGUAGE (t)), v); if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! gcc_unreachable (); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) v = iterative_hash (t, sizeof (struct cl_optimization), v); *************** hash_tree (struct streamer_tree_cache_d *** 986,992 **** if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) { visit (DECL_FUNCTION_PERSONALITY (t)); ! visit (DECL_FUNCTION_SPECIFIC_TARGET (t)); visit (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t)); } --- 986,992 ---- if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) { visit (DECL_FUNCTION_PERSONALITY (t)); ! /* Do not follow DECL_FUNCTION_SPECIFIC_TARGET. */ visit (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t)); } Index: gcc/tree-streamer-out.c =================================================================== *** gcc/tree-streamer-out.c (revision 207756) --- gcc/tree-streamer-out.c (working copy) *************** pack_ts_translation_unit_decl_value_fiel *** 353,376 **** bp_pack_string (ob, bp, TRANSLATION_UNIT_LANGUAGE (expr), true); } - /* Pack a TS_TARGET_OPTION tree in EXPR to BP. */ - - static void - pack_ts_target_option (struct bitpack_d *bp, tree expr) - { - struct cl_target_option *t = TREE_TARGET_OPTION (expr); - unsigned i, len; - - /* The cl_target_option is target specific and generated by the options - awk script, so we just recreate a byte-by-byte copy here. */ - - len = sizeof (struct cl_target_option); - for (i = 0; i < len; i++) - bp_pack_value (bp, ((unsigned char *)t)[i], 8); - /* Catch struct size mismatches between reader and writer. */ - bp_pack_value (bp, 0x12345678, 32); - } - /* Pack a TS_OPTIMIZATION tree in EXPR to BP. */ static void --- 353,358 ---- *************** streamer_pack_tree_bitfields (struct out *** 481,487 **** pack_ts_translation_unit_decl_value_fields (ob, bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! pack_ts_target_option (bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) pack_ts_optimization (bp, expr); --- 463,469 ---- pack_ts_translation_unit_decl_value_fields (ob, bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! gcc_unreachable (); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) pack_ts_optimization (bp, expr); *************** write_ts_function_decl_tree_pointers (st *** 716,722 **** /* DECL_STRUCT_FUNCTION is handled by lto_output_function. FIXME lto, maybe it should be handled here? */ stream_write_tree (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p); ! stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p); stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr), ref_p); } --- 698,704 ---- /* DECL_STRUCT_FUNCTION is handled by lto_output_function. FIXME lto, maybe it should be handled here? */ stream_write_tree (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p); ! /* DECL_FUNCTION_SPECIFIC_TARGET is regenerated. */ stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr), ref_p); } Index: gcc/tree-streamer-in.c =================================================================== *** gcc/tree-streamer-in.c (revision 207756) --- gcc/tree-streamer-in.c (working copy) *************** unpack_ts_translation_unit_decl_value_fi *** 394,414 **** vec_safe_push (all_translation_units, expr); } - /* Unpack a TS_TARGET_OPTION tree from BP into EXPR. */ - - static void - unpack_ts_target_option (struct bitpack_d *bp, tree expr) - { - unsigned i, len; - struct cl_target_option *t = TREE_TARGET_OPTION (expr); - - len = sizeof (struct cl_target_option); - for (i = 0; i < len; i++) - ((unsigned char *)t)[i] = bp_unpack_value (bp, 8); - if (bp_unpack_value (bp, 32) != 0x12345678) - fatal_error ("cl_target_option size mismatch in LTO reader and writer"); - } - /* Unpack a TS_OPTIMIZATION tree from BP into EXPR. */ static void --- 394,399 ---- *************** unpack_value_fields (struct data_in *dat *** 517,523 **** unpack_ts_translation_unit_decl_value_fields (data_in, bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! unpack_ts_target_option (bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) unpack_ts_optimization (bp, expr); --- 502,508 ---- unpack_ts_translation_unit_decl_value_fields (data_in, bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! gcc_unreachable (); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) unpack_ts_optimization (bp, expr); *************** lto_input_ts_function_decl_tree_pointers *** 796,802 **** /* DECL_STRUCT_FUNCTION is handled by lto_input_function. FIXME lto, maybe it should be handled here? */ DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree (ib, data_in); ! DECL_FUNCTION_SPECIFIC_TARGET (expr) = stream_read_tree (ib, data_in); DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = stream_read_tree (ib, data_in); /* If the file contains a function with an EH personality set, --- 781,787 ---- /* DECL_STRUCT_FUNCTION is handled by lto_input_function. FIXME lto, maybe it should be handled here? */ DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree (ib, data_in); ! /* DECL_FUNCTION_SPECIFIC_TARGET is regenerated from attributes. */ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = stream_read_tree (ib, data_in); /* If the file contains a function with an EH personality set, Index: gcc/lto/lto.c =================================================================== *** gcc/lto/lto.c (revision 207756) --- gcc/lto/lto.c (working copy) *************** compare_tree_sccs_1 (tree t1, tree t2, t *** 1367,1375 **** return false; if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! if (memcmp (TREE_TARGET_OPTION (t1), TREE_TARGET_OPTION (t2), ! sizeof (struct cl_target_option)) != 0) ! return false; if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) if (memcmp (TREE_OPTIMIZATION (t1), TREE_OPTIMIZATION (t2), --- 1367,1373 ---- return false; if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)) ! gcc_unreachable (); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) if (memcmp (TREE_OPTIMIZATION (t1), TREE_OPTIMIZATION (t2), *************** compare_tree_sccs_1 (tree t1, tree t2, t *** 1547,1554 **** { compare_tree_edges (DECL_FUNCTION_PERSONALITY (t1), DECL_FUNCTION_PERSONALITY (t2)); ! compare_tree_edges (DECL_FUNCTION_SPECIFIC_TARGET (t1), ! DECL_FUNCTION_SPECIFIC_TARGET (t2)); compare_tree_edges (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t1), DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t2)); } --- 1545,1552 ---- { compare_tree_edges (DECL_FUNCTION_PERSONALITY (t1), DECL_FUNCTION_PERSONALITY (t2)); ! /* DECL_FUNCTION_SPECIFIC_TARGET is not yet created. We compare ! the attribute list instead. */ compare_tree_edges (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t1), DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t2)); } *************** lto_read_decls (struct lto_file_decl_dat *** 1926,1931 **** --- 1924,1938 ---- if (TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t)) cache_integer_cst (t); + /* Re-build DECL_FUNCTION_SPECIFIC_TARGET, we need that + for both WPA and LTRANS stage. */ + if (TREE_CODE (t) == FUNCTION_DECL) + { + tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (t)); + if (attr) + targetm.target_option.valid_attribute_p + (t, NULL_TREE, TREE_VALUE (attr), 0); + } /* Register TYPE_DECLs with the debuginfo machinery. */ if (!flag_wpa && TREE_CODE (t) == TYPE_DECL)