aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/tree-cfg.c')
-rw-r--r--gcc-4.9/gcc/tree-cfg.c106
1 files changed, 61 insertions, 45 deletions
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);