From e97c99f15937e5762a973b25192aab824126a6d3 Mon Sep 17 00:00:00 2001 From: Rong Xu Date: Tue, 2 Sep 2014 15:29:57 -0700 Subject: [gcc-4.9] Merge svn r214745 from google/gcc-4_9 branch. Merge gcc-4_9 source r214745 from google/gcc-4_9 branch. Change-Id: Ie6fa0fd72f4b4eec3adc4db4bb922e652d1c2605 --- gcc-4.9/gcc/tree-cfg.c | 106 ++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 45 deletions(-) (limited to 'gcc-4.9/gcc/tree-cfg.c') diff --git a/gcc-4.9/gcc/tree-cfg.c b/gcc-4.9/gcc/tree-cfg.c index d9896e76f..29aa8c7a7 100644 --- a/gcc-4.9/gcc/tree-cfg.c +++ b/gcc-4.9/gcc/tree-cfg.c @@ -112,7 +112,14 @@ static struct cfg_stats_d cfg_stats; struct locus_discrim_map { location_t locus; - int discriminator; + /* Different calls belonging to the same source line will be assigned + different discriminators. But we want to keep the discriminator of + the first call in the same source line to be 0, in order to reduce + the .debug_line section size. needs_increment is used for this + purpose. It is initialized as false and will be set to true after + the first call is seen. */ + bool needs_increment:1; + int discriminator:31; }; /* Hashtable helpers. */ @@ -164,6 +171,7 @@ static int gimple_verify_flow_info (void); static void gimple_make_forwarder_block (edge); static gimple first_non_label_stmt (basic_block); static bool verify_gimple_transaction (gimple); +static bool call_can_make_abnormal_goto (gimple); /* Flowgraph optimization and cleanup. */ static void gimple_merge_blocks (basic_block, basic_block); @@ -426,6 +434,32 @@ assert_unreachable_fallthru_edge_p (edge e) } +/* Initialize GF_CALL_CTRL_ALTERING flag, which indicates the call + could alter control flow except via eh. We initialize the flag at + CFG build time and only ever clear it later. */ + +static void +gimple_call_initialize_ctrl_altering (gimple stmt) +{ + int flags = gimple_call_flags (stmt); + + /* A call alters control flow if it can make an abnormal goto. */ + if (call_can_make_abnormal_goto (stmt) + /* A call also alters control flow if it does not return. */ + || flags & ECF_NORETURN + /* TM ending statements have backedges out of the transaction. + Return true so we split the basic block containing them. + Note that the TM_BUILTIN test is merely an optimization. */ + || ((flags & ECF_TM_BUILTIN) + && is_tm_ending_fndecl (gimple_call_fndecl (stmt))) + /* BUILT_IN_RETURN call is same as return statement. */ + || gimple_call_builtin_p (stmt, BUILT_IN_RETURN)) + gimple_call_set_ctrl_altering (stmt, true); + else + gimple_call_set_ctrl_altering (stmt, false); +} + + /* Build a flowgraph for the sequence of stmts SEQ. */ static void @@ -444,6 +478,9 @@ make_blocks (gimple_seq seq) prev_stmt = stmt; stmt = gsi_stmt (i); + if (stmt && is_gimple_call (stmt)) + gimple_call_initialize_ctrl_altering (stmt); + /* If the statement starts a new basic block or if we have determined in a previous pass that we need to create a new block for STMT, do so now. */ @@ -914,10 +951,15 @@ make_edges (void) /* Find the next available discriminator value for LOCUS. The discriminator distinguishes among several basic blocks that share a common locus, allowing for more accurate sample-based - profiling. */ + profiling. If RETURN_NEXT is true, return the next discriminator + anyway. If RETURN_NEXT is not true, we may not increase the + discriminator if locus_discrim_map::needs_increment is false, + which is used when the stmt is the first call stmt in current + source line. locus_discrim_map::needs_increment will be set to + true after the first call is seen. */ static int -next_discriminator_for_locus (location_t locus) +next_discriminator_for_locus (location_t locus, bool return_next) { struct locus_discrim_map item; struct locus_discrim_map **slot; @@ -932,9 +974,13 @@ next_discriminator_for_locus (location_t locus) *slot = XNEW (struct locus_discrim_map); gcc_assert (*slot); (*slot)->locus = locus; + (*slot)->needs_increment = false; (*slot)->discriminator = 0; } - (*slot)->discriminator++; + if (return_next || (*slot)->needs_increment) + (*slot)->discriminator++; + else + (*slot)->needs_increment = true; return (*slot)->discriminator; } @@ -974,7 +1020,7 @@ assign_discriminator (location_t locus, basic_block bb) if (locus == UNKNOWN_LOCATION) return; - discriminator = next_discriminator_for_locus (locus); + discriminator = next_discriminator_for_locus (locus, true); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -1009,23 +1055,13 @@ assign_discriminators (void) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); - if (curr_locus == UNKNOWN_LOCATION) - { + if (gimple_code (stmt) == GIMPLE_CALL) + { curr_locus = gimple_location (stmt); - } - else if (!same_line_p (curr_locus, gimple_location (stmt))) - { - curr_locus = gimple_location (stmt); - curr_discr = 0; - } - else if (curr_discr != 0) - { + curr_discr = next_discriminator_for_locus (curr_locus, false); gimple_set_location (stmt, location_with_discriminator ( - gimple_location (stmt), curr_discr)); + curr_locus, curr_discr)); } - /* Allocate a new discriminator for CALL stmt. */ - if (gimple_code (stmt) == GIMPLE_CALL) - curr_discr = next_discriminator_for_locus (curr_locus); } if (locus == UNKNOWN_LOCATION) @@ -2416,28 +2452,10 @@ is_ctrl_altering_stmt (gimple t) switch (gimple_code (t)) { case GIMPLE_CALL: - { - int flags = gimple_call_flags (t); - - /* A call alters control flow if it can make an abnormal goto. */ - if (call_can_make_abnormal_goto (t)) - return true; - - /* A call also alters control flow if it does not return. */ - if (flags & ECF_NORETURN) - return true; - - /* TM ending statements have backedges out of the transaction. - Return true so we split the basic block containing them. - Note that the TM_BUILTIN test is merely an optimization. */ - if ((flags & ECF_TM_BUILTIN) - && is_tm_ending_fndecl (gimple_call_fndecl (t))) - return true; - - /* BUILT_IN_RETURN call is same as return statement. */ - if (gimple_call_builtin_p (t, BUILT_IN_RETURN)) - return true; - } + /* Per stmt call flag indicates whether the call could alter + controlflow. */ + if (gimple_call_ctrl_altering_p (t)) + return true; break; case GIMPLE_EH_DISPATCH: @@ -8579,6 +8597,8 @@ execute_fixup_cfg (void) && (!is_gimple_call (stmt) || (gimple_call_flags (stmt) & ECF_NORETURN) == 0))) { + if (stmt && is_gimple_call (stmt)) + gimple_call_set_ctrl_altering (stmt, false); stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0); gimple_stmt_iterator gsi = gsi_last_bb (bb); @@ -8589,10 +8609,6 @@ execute_fixup_cfg (void) 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); -- cgit v1.2.3