Hi, until recently we did not have thunks with incoming edges in the call graph. However, speculative devirtualization can introduce them which may lead to creation of new SCCs in the call graph. What is more, ipa_reduced_postorder called with reduce parameter set to true may decide to represent the whole SCC with the thunk which will in turn currently cause propagate_constants_topo from IPA-CP to ignore the whole SCC and make ipcp_verify_propagated_values fail later. This happens for example when compiling Mozilla Firefox (I did it with LTO but it failed even when creating a fat unit object file). I believe Honza has this check disabled for this reason.
The patch below fixes propagate_constants_topo by making it check each node in the SCC rather than just the leading one. I have also changed it to use ipa_get_nodes_in_cycle rather than loop through dfs_infos since that seems to be the documented way of iterating over SCCs. (And I should probably move edge_within_scc to ipa-utils too.) Bootstrapped and tested on x86_64-linux, I have also successfully LTO-built Firefox with this patch. OK for trunk? Thanks, Martin 2013-09-09 Martin Jambor <mjam...@suse.cz> * ipa-cp.c (propagate_constants_topo): Do not ignore SCC represented by a thunk. Index: src/gcc/ipa-cp.c =================================================================== *** src.orig/gcc/ipa-cp.c --- src/gcc/ipa-cp.c *************** propagate_constants_topo (struct topo_in *** 2113,2135 **** for (i = topo->nnodes - 1; i >= 0; i--) { struct cgraph_node *v, *node = topo->order[i]; ! struct ipa_dfs_info *node_dfs_info; - if (!cgraph_function_with_gimple_body_p (node)) - continue; - - node_dfs_info = (struct ipa_dfs_info *) node->symbol.aux; /* First, iteratively propagate within the strongly connected component until all lattices stabilize. */ ! v = node_dfs_info->next_cycle; ! while (v) ! { push_node_to_stack (topo, v); - v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle; - } ! v = node; while (v) { struct cgraph_edge *cs; --- 2113,2129 ---- for (i = topo->nnodes - 1; i >= 0; i--) { + unsigned j; struct cgraph_node *v, *node = topo->order[i]; ! vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node); /* First, iteratively propagate within the strongly connected component until all lattices stabilize. */ ! FOR_EACH_VEC_ELT (cycle_nodes, j, v) ! if (cgraph_function_with_gimple_body_p (v)) push_node_to_stack (topo, v); ! v = pop_node_from_stack (topo); while (v) { struct cgraph_edge *cs; *************** propagate_constants_topo (struct topo_in *** 2144,2162 **** /* Afterwards, propagate along edges leading out of the SCC, calculates the local effects of the discovered constants and all valid values to their topological sort. */ ! v = node; ! while (v) ! { ! struct cgraph_edge *cs; ! ! estimate_local_effects (v); ! add_all_node_vals_to_toposort (v); ! for (cs = v->callees; cs; cs = cs->next_callee) ! if (!edge_within_scc (cs)) ! propagate_constants_accross_call (cs); ! ! v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle; ! } } } --- 2138,2155 ---- /* Afterwards, propagate along edges leading out of the SCC, calculates the local effects of the discovered constants and all valid values to their topological sort. */ ! FOR_EACH_VEC_ELT (cycle_nodes, j, v) ! if (cgraph_function_with_gimple_body_p (v)) ! { ! struct cgraph_edge *cs; ! ! estimate_local_effects (v); ! add_all_node_vals_to_toposort (v); ! for (cs = v->callees; cs; cs = cs->next_callee) ! if (!edge_within_scc (cs)) ! propagate_constants_accross_call (cs); ! } ! cycle_nodes.release (); } }