void gsi_move_to_bb_end (gimple_stmt_iterator *from, basic_block bb) { gimple_stmt_iterator last = gsi_last_bb (bb); gcc_checking_assert (gsi_bb (last) == bb); /* Have to check gsi_end_p because it could be an empty block. */ if (!gsi_end_p (last) && is_ctrl_stmt (gsi_stmt (last))) gsi_move_before (from, &last); else gsi_move_after (from, &last); }
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; }