Hi, while playing around with devirtualization I tried to make it to always produce builtin_unreachable (). This makes early inliner to ICE, since the callgraph edges are not properly updated after folding. This is because cgraph_update_edges_for_call_stmt is called on a wrong statement.
Does something like this look resonable? Honza * tree-inline.c (fold_marked_statements): Correctly handle cases where folding produes extra statement. Index: tree-inline.c =================================================================== --- tree-inline.c (revision 207438) +++ tree-inline.c (working copy) @@ -4480,8 +4480,14 @@ fold_marked_statements (int first, struc if (pointer_set_contains (statements, gsi_stmt (gsi))) { gimple old_stmt = gsi_stmt (gsi); + gimple_stmt_iterator prev = gsi; + gimple prev_stmt = NULL; tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0; + gsi_prev (&prev); + if (!gsi_end_p (prev)) + prev_stmt = gsi_stmt (prev); + if (old_decl && DECL_BUILT_IN (old_decl)) { /* Folding builtins can create multiple instructions, @@ -4541,8 +4547,31 @@ fold_marked_statements (int first, struc if (is_gimple_call (old_stmt) || is_gimple_call (new_stmt)) - cgraph_update_edges_for_call_stmt (old_stmt, old_decl, - new_stmt); + { + if (!is_gimple_call (new_stmt)) + { + prev = gsi; + gsi_prev (&prev); + + /* Fold stmt may turn + + retval = call (); + + statement into + + __builtin_unreachable (); + retval = dummy. + + Be sure to look up the call. */ + + if (!gsi_end_p (prev) + && gsi_stmt (prev) != prev_stmt + && is_gimple_call (gsi_stmt (prev))) + new_stmt = gsi_stmt (prev); + } + cgraph_update_edges_for_call_stmt (old_stmt, old_decl, + new_stmt); + } if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt)) gimple_purge_dead_eh_edges (BASIC_BLOCK_FOR_FN (cfun,