re PR lto/60449 (Merging function DECLs discards leaf attribute which causes cfg verifier to fail)
2014-08-20 Martin Jambor <mjambor@suse.cz> Wei Mi <wmi@google.com> PR ipa/60449 PR middle-end/61776 * tree-ssa-operands.c (update_stmt_operands): Remove MODIFIED_NORETURN_CALLS. * tree-cfgcleanup.c (cleanup_call_ctrl_altering_flag): New func. (cleanup_control_flow_bb): Use cleanup_call_ctrl_altering_flag. (split_bb_on_noreturn_calls): Renamed from split_bbs_on_noreturn_calls. (cleanup_tree_cfg_1): Use split_bb_on_noreturn_calls. * tree-ssanames.h: Remove MODIFIED_NORETURN_CALLS. * gimple.h (enum gf_mask): Add GF_CALL_CTRL_ALTERING. (gimple_call_set_ctrl_altering): New func. (gimple_call_ctrl_altering_p): Ditto. * tree-cfg.c (gimple_call_initialize_ctrl_altering): Ditto. (make_blocks): Use gimple_call_initialize_ctrl_altering. (is_ctrl_altering_stmt): Use gimple_call_ctrl_altering_p. (execute_fixup_cfg): Use gimple_call_ctrl_altering_p and remove MODIFIED_NORETURN_CALLS. 2014-08-20 Martin Jambor <mjambor@suse.cz> Wei Mi <wmi@google.com> PR ipa/60449 PR middle-end/61776 * testsuite/gcc.dg/lto/pr60449_1.c: New test. * testsuite/gcc.dg/lto/pr60449_0.c: New test. * testsuite/gcc.dg/pr61776.c: New test. Co-Authored-By: Wei Mi <wmi@google.com> From-SVN: r214233
This commit is contained in:
parent
7e04426135
commit
58041fe6cf
@ -1,3 +1,24 @@
|
||||
2014-08-20 Martin Jambor <mjambor@suse.cz>
|
||||
Wei Mi <wmi@google.com>
|
||||
|
||||
PR ipa/60449
|
||||
PR middle-end/61776
|
||||
* tree-ssa-operands.c (update_stmt_operands): Remove
|
||||
MODIFIED_NORETURN_CALLS.
|
||||
* tree-cfgcleanup.c (cleanup_call_ctrl_altering_flag): New func.
|
||||
(cleanup_control_flow_bb): Use cleanup_call_ctrl_altering_flag.
|
||||
(split_bb_on_noreturn_calls): Renamed from split_bbs_on_noreturn_calls.
|
||||
(cleanup_tree_cfg_1): Use split_bb_on_noreturn_calls.
|
||||
* tree-ssanames.h: Remove MODIFIED_NORETURN_CALLS.
|
||||
* gimple.h (enum gf_mask): Add GF_CALL_CTRL_ALTERING.
|
||||
(gimple_call_set_ctrl_altering): New func.
|
||||
(gimple_call_ctrl_altering_p): Ditto.
|
||||
* tree-cfg.c (gimple_call_initialize_ctrl_altering): Ditto.
|
||||
(make_blocks): Use gimple_call_initialize_ctrl_altering.
|
||||
(is_ctrl_altering_stmt): Use gimple_call_ctrl_altering_p.
|
||||
(execute_fixup_cfg): Use gimple_call_ctrl_altering_p and
|
||||
remove MODIFIED_NORETURN_CALLS.
|
||||
|
||||
2014-08-20 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* coverage.c (coverage_compute_profile_id): Return non-0;
|
||||
|
24
gcc/gimple.h
24
gcc/gimple.h
@ -90,6 +90,7 @@ enum gf_mask {
|
||||
GF_CALL_NOTHROW = 1 << 4,
|
||||
GF_CALL_ALLOCA_FOR_VAR = 1 << 5,
|
||||
GF_CALL_INTERNAL = 1 << 6,
|
||||
GF_CALL_CTRL_ALTERING = 1 << 7,
|
||||
GF_OMP_PARALLEL_COMBINED = 1 << 0,
|
||||
GF_OMP_FOR_KIND_MASK = (1 << 2) - 1,
|
||||
GF_OMP_FOR_KIND_FOR = 0,
|
||||
@ -2459,6 +2460,29 @@ gimple_call_internal_fn (const_gimple gs)
|
||||
return static_cast <const gimple_statement_call *> (gs)->u.internal_fn;
|
||||
}
|
||||
|
||||
/* If CTRL_ALTERING_P is true, mark GIMPLE_CALL S to be a stmt
|
||||
that could alter control flow. */
|
||||
|
||||
static inline void
|
||||
gimple_call_set_ctrl_altering (gimple s, bool ctrl_altering_p)
|
||||
{
|
||||
GIMPLE_CHECK (s, GIMPLE_CALL);
|
||||
if (ctrl_altering_p)
|
||||
s->subcode |= GF_CALL_CTRL_ALTERING;
|
||||
else
|
||||
s->subcode &= ~GF_CALL_CTRL_ALTERING;
|
||||
}
|
||||
|
||||
/* Return true if call GS calls an func whose GF_CALL_CTRL_ALTERING
|
||||
flag is set. Such call could not be a stmt in the middle of a bb. */
|
||||
|
||||
static inline bool
|
||||
gimple_call_ctrl_altering_p (const_gimple gs)
|
||||
{
|
||||
GIMPLE_CHECK (gs, GIMPLE_CALL);
|
||||
return (gs->subcode & GF_CALL_CTRL_ALTERING) != 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return the function type of the function called by GS. */
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2014-08-20 Martin Jambor <mjambor@suse.cz>
|
||||
Wei Mi <wmi@google.com>
|
||||
|
||||
PR ipa/60449
|
||||
PR middle-end/61776
|
||||
* testsuite/gcc.dg/lto/pr60449_1.c: New test.
|
||||
* testsuite/gcc.dg/lto/pr60449_0.c: New test.
|
||||
* testsuite/gcc.dg/pr61776.c: New test.
|
||||
|
||||
2014-08-20 Steve Ellcey <sellcey@mips.com>
|
||||
|
||||
PR middle-end/49191
|
||||
|
@ -164,6 +164,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);
|
||||
@ -437,6 +438,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
|
||||
@ -455,6 +482,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. */
|
||||
@ -2372,28 +2402,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:
|
||||
@ -8533,6 +8545,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);
|
||||
@ -8543,10 +8557,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);
|
||||
|
@ -162,6 +162,23 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Cleanup the GF_CALL_CTRL_ALTERING flag according to
|
||||
to updated gimple_call_flags. */
|
||||
|
||||
static void
|
||||
cleanup_call_ctrl_altering_flag (gimple bb_end)
|
||||
{
|
||||
if (!is_gimple_call (bb_end)
|
||||
|| !gimple_call_ctrl_altering_p (bb_end))
|
||||
return;
|
||||
|
||||
int flags = gimple_call_flags (bb_end);
|
||||
if (((flags & (ECF_CONST | ECF_PURE))
|
||||
&& !(flags & ECF_LOOPING_CONST_OR_PURE))
|
||||
|| (flags & ECF_LEAF))
|
||||
gimple_call_set_ctrl_altering (bb_end, false);
|
||||
}
|
||||
|
||||
/* Try to remove superfluous control structures in basic block BB. Returns
|
||||
true if anything changes. */
|
||||
|
||||
@ -182,6 +199,9 @@ cleanup_control_flow_bb (basic_block bb)
|
||||
|
||||
stmt = gsi_stmt (gsi);
|
||||
|
||||
/* Try to cleanup ctrl altering flag for call which ends bb. */
|
||||
cleanup_call_ctrl_altering_flag (stmt);
|
||||
|
||||
if (gimple_code (stmt) == GIMPLE_COND
|
||||
|| gimple_code (stmt) == GIMPLE_SWITCH)
|
||||
retval |= cleanup_control_expr_graph (bb, gsi);
|
||||
@ -594,30 +614,24 @@ fixup_noreturn_call (gimple stmt)
|
||||
known not to return, and remove the unreachable code. */
|
||||
|
||||
static bool
|
||||
split_bbs_on_noreturn_calls (void)
|
||||
split_bb_on_noreturn_calls (basic_block bb)
|
||||
{
|
||||
bool changed = false;
|
||||
gimple stmt;
|
||||
basic_block bb;
|
||||
gimple_stmt_iterator gsi;
|
||||
|
||||
/* Detect cases where a mid-block call is now known not to return. */
|
||||
if (cfun->gimple_df)
|
||||
while (vec_safe_length (MODIFIED_NORETURN_CALLS (cfun)))
|
||||
{
|
||||
stmt = MODIFIED_NORETURN_CALLS (cfun)->pop ();
|
||||
bb = gimple_bb (stmt);
|
||||
/* BB might be deleted at this point, so verify first
|
||||
BB is present in the cfg. */
|
||||
if (bb == NULL
|
||||
|| bb->index < NUM_FIXED_BLOCKS
|
||||
|| bb->index >= last_basic_block_for_fn (cfun)
|
||||
|| BASIC_BLOCK_FOR_FN (cfun, bb->index) != bb
|
||||
|| !gimple_call_noreturn_p (stmt))
|
||||
continue;
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
|
||||
if (!is_gimple_call (stmt))
|
||||
continue;
|
||||
|
||||
if (gimple_call_noreturn_p (stmt))
|
||||
changed |= fixup_noreturn_call (stmt);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
bitmap_set_bit (cfgcleanup_altered_bbs, bb->index);
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -655,8 +669,6 @@ cleanup_tree_cfg_1 (void)
|
||||
basic_block bb;
|
||||
unsigned i, n;
|
||||
|
||||
retval |= split_bbs_on_noreturn_calls ();
|
||||
|
||||
/* Prepare the worklists of altered blocks. */
|
||||
cfgcleanup_altered_bbs = BITMAP_ALLOC (NULL);
|
||||
|
||||
@ -672,7 +684,10 @@ cleanup_tree_cfg_1 (void)
|
||||
{
|
||||
bb = BASIC_BLOCK_FOR_FN (cfun, i);
|
||||
if (bb)
|
||||
retval |= cleanup_tree_cfg_bb (bb);
|
||||
{
|
||||
retval |= cleanup_tree_cfg_bb (bb);
|
||||
retval |= split_bb_on_noreturn_calls (bb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now process the altered blocks, as long as any are available. */
|
||||
@ -689,9 +704,9 @@ cleanup_tree_cfg_1 (void)
|
||||
|
||||
retval |= cleanup_tree_cfg_bb (bb);
|
||||
|
||||
/* Rerun split_bbs_on_noreturn_calls, in case we have altered any noreturn
|
||||
/* Rerun split_bb_on_noreturn_calls, in case we have altered any noreturn
|
||||
calls. */
|
||||
retval |= split_bbs_on_noreturn_calls ();
|
||||
retval |= split_bb_on_noreturn_calls (bb);
|
||||
}
|
||||
|
||||
end_recording_case_labels ();
|
||||
|
@ -1087,12 +1087,6 @@ update_stmt_operands (struct function *fn, gimple stmt)
|
||||
|
||||
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 (MODIFIED_NORETURN_CALLS (fn), stmt);
|
||||
|
||||
gcc_assert (gimple_modified_p (stmt));
|
||||
build_ssa_operands (fn, stmt);
|
||||
gimple_set_modified (stmt, false);
|
||||
|
@ -57,7 +57,6 @@ struct GTY ((variable_size)) range_info_def {
|
||||
|
||||
|
||||
#define SSANAMES(fun) (fun)->gimple_df->ssa_names
|
||||
#define MODIFIED_NORETURN_CALLS(fun) (fun)->gimple_df->modified_noreturn_calls
|
||||
#define DEFAULT_DEFS(fun) (fun)->gimple_df->default_defs
|
||||
|
||||
#define num_ssa_names (vec_safe_length (cfun->gimple_df->ssa_names))
|
||||
|
Loading…
Reference in New Issue
Block a user