void update_stmt_operands (gimple stmt) { /* If update_stmt_operands is called before SSA is initialized, do nothing. */ if (!ssa_operands_active ()) return; timevar_push (TV_TREE_OPS); /* If the stmt is a noreturn call queue it to be processed by split_bbs_on_noreturn_calls during cfg cleanup. */ if (is_gimple_call (stmt) && gimple_call_noreturn_p (stmt)) VEC_safe_push (gimple, gc, MODIFIED_NORETURN_CALLS (cfun), stmt); gcc_assert (gimple_modified_p (stmt)); build_ssa_operands (stmt); gimple_set_modified (stmt, false); timevar_pop (TV_TREE_OPS); }
unsigned int execute_fixup_cfg (void) { basic_block bb; gimple_stmt_iterator gsi; int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0; gcov_type count_scale; edge e; edge_iterator ei; count_scale = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count, ENTRY_BLOCK_PTR->count); ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count; EXIT_BLOCK_PTR->count = apply_scale (EXIT_BLOCK_PTR->count, count_scale); FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) e->count = apply_scale (e->count, count_scale); FOR_EACH_BB (bb) { bb->count = apply_scale (bb->count, count_scale); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); tree decl = is_gimple_call (stmt) ? gimple_call_fndecl (stmt) : NULL; if (decl) { int flags = gimple_call_flags (stmt); if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) { if (gimple_purge_dead_abnormal_call_edges (bb)) todo |= TODO_cleanup_cfg; if (gimple_in_ssa_p (cfun)) { todo |= TODO_update_ssa | TODO_cleanup_cfg; update_stmt (stmt); } } if (flags & ECF_NORETURN && fixup_noreturn_call (stmt)) todo |= TODO_cleanup_cfg; } if (maybe_clean_eh_stmt (stmt) && gimple_purge_dead_eh_edges (bb)) todo |= TODO_cleanup_cfg; } FOR_EACH_EDGE (e, ei, bb->succs) e->count = apply_scale (e->count, count_scale); /* If we have a basic block with no successors that does not end with a control statement or a noreturn call end it with a call to __builtin_unreachable. This situation can occur when inlining a noreturn call that does in fact return. */ if (EDGE_COUNT (bb->succs) == 0) { gimple stmt = last_stmt (bb); if (!stmt || (!is_ctrl_stmt (stmt) && (!is_gimple_call (stmt) || (gimple_call_flags (stmt) & ECF_NORETURN) == 0))) { stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0); gimple_stmt_iterator gsi = gsi_last_bb (bb); gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); } } } if (count_scale != REG_BR_PROB_BASE) compute_function_frequency (); /* We just processed all calls. */ if (cfun->gimple_df) vec_free (MODIFIED_NORETURN_CALLS (cfun)); /* Dump a textual representation of the flowgraph. */ if (dump_file) gimple_dump_cfg (dump_file, dump_flags); if (current_loops && (todo & TODO_cleanup_cfg)) loops_state_set (LOOPS_NEED_FIXUP); return todo; }
unsigned int execute_fixup_cfg (void) { basic_block bb; gimple_stmt_iterator gsi; int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0; gcov_type count_scale; edge e; edge_iterator ei; if (ENTRY_BLOCK_PTR->count) count_scale = (cgraph_node (current_function_decl)->count * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2) / ENTRY_BLOCK_PTR->count; else count_scale = REG_BR_PROB_BASE; ENTRY_BLOCK_PTR->count = cgraph_node (current_function_decl)->count; EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; FOR_EACH_BB (bb) { bb->count = (bb->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); tree decl = is_gimple_call (stmt) ? gimple_call_fndecl (stmt) : NULL; if (decl) { int flags = gimple_call_flags (stmt); if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) { if (gimple_in_ssa_p (cfun)) { todo |= TODO_update_ssa | TODO_cleanup_cfg; mark_symbols_for_renaming (stmt); update_stmt (stmt); } } if (flags & ECF_NORETURN && fixup_noreturn_call (stmt)) todo |= TODO_cleanup_cfg; } maybe_clean_eh_stmt (stmt); } if (gimple_purge_dead_eh_edges (bb)) todo |= TODO_cleanup_cfg; FOR_EACH_EDGE (e, ei, bb->succs) e->count = (e->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; } if (count_scale != REG_BR_PROB_BASE) compute_function_frequency (); /* We just processed all calls. */ if (cfun->gimple_df) { VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun)); MODIFIED_NORETURN_CALLS (cfun) = NULL; } /* Dump a textual representation of the flowgraph. */ if (dump_file) gimple_dump_cfg (dump_file, dump_flags); return todo; }