Commit 6728ee79 by Michael Matz Committed by Michael Matz

re PR middle-end/41573 (segfault in trunk related to strings)

	PR middle-end/41573
	* builtins.c (fold_builtin_isascii): Use fold_build2.
	(fold_builtin_isdigit): Ditto.
	* except.c (duplicate_eh_regions_1): Tolerate NULL labels.
	* tree-cfg.c (struct rus_data, remove_useless_stmts_warn_notreached,
	remove_useless_stmts_cond, remove_useless_stmts_tf,
	remove_useless_stmts_tc, remove_useless_stmts_bind,
	remove_useless_stmts_goto, remove_useless_stmts_label,
	remove_useless_stmts_1, remove_useless_stmts,
	pass_remove_useless_stmts): Remove.
	* tree-pass.h (pass_remove_useless_stmts): Don't declare.
	* passes.c (init_optimization_passes): Don't add
	pass_remove_useless_stmts.
	* tree-eh.c (lower_eh_constructs_2): Handle empty cleanups.
	* tree.c (free_lang_data_in_decl): Don't clear DECL_INITIAL of
	static constants.
	* lto-symtab.c (lto_symtab_register_decl): Accepts DECL_INITIAL
	for static constants.
	* lto-streamer-out.c (output_gimple_stmt): Handle GIMPLE_NOP.
	* lto-streamer-in.c (input_gimple_stmt): Handle GIMPLE_NOP.

testsuite/
	* gcc.dg/tree-ssa/foldstring-1.c: Use fre dump.
	* gcc.dg/tree-ssa/useless-1.c: Use gimple dump.
	* gcc.dg/pr41573.c: New test.

From-SVN: r152563
parent 0d0bfe17
2009-10-08 Michael Matz <matz@suse.de>
PR middle-end/41573
* builtins.c (fold_builtin_isascii): Use fold_build2.
(fold_builtin_isdigit): Ditto.
* except.c (duplicate_eh_regions_1): Tolerate NULL labels.
* tree-cfg.c (struct rus_data, remove_useless_stmts_warn_notreached,
remove_useless_stmts_cond, remove_useless_stmts_tf,
remove_useless_stmts_tc, remove_useless_stmts_bind,
remove_useless_stmts_goto, remove_useless_stmts_label,
remove_useless_stmts_1, remove_useless_stmts,
pass_remove_useless_stmts): Remove.
* tree-pass.h (pass_remove_useless_stmts): Don't declare.
* passes.c (init_optimization_passes): Don't add
pass_remove_useless_stmts.
* tree-eh.c (lower_eh_constructs_2): Handle empty cleanups.
* tree.c (free_lang_data_in_decl): Don't clear DECL_INITIAL of
static constants.
* lto-symtab.c (lto_symtab_register_decl): Accepts DECL_INITIAL
for static constants.
* lto-streamer-out.c (output_gimple_stmt): Handle GIMPLE_NOP.
* lto-streamer-in.c (input_gimple_stmt): Handle GIMPLE_NOP.
2009-10-08 Richard Guenther <rguenther@suse.de>
* gimple.c (free_gimple_type_tables): New function.
......@@ -9238,7 +9238,7 @@ fold_builtin_isascii (location_t loc, tree arg)
else
{
/* Transform isascii(c) -> ((c & ~0x7f) == 0). */
arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
build_int_cst (NULL_TREE,
~ (unsigned HOST_WIDE_INT) 0x7f));
return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
......@@ -9278,7 +9278,7 @@ fold_builtin_isdigit (location_t loc, tree arg)
return NULL_TREE;
arg = fold_convert_loc (loc, unsigned_type_node, arg);
arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
build_int_cst (unsigned_type_node, target_digit0));
return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
build_int_cst (unsigned_type_node, 9));
......
......@@ -552,8 +552,11 @@ duplicate_eh_regions_1 (struct duplicate_eh_regions_data *data,
case ERT_ALLOWED_EXCEPTIONS:
new_r->u.allowed.type_list = old_r->u.allowed.type_list;
if (old_r->u.allowed.label)
new_r->u.allowed.label
= data->label_map (old_r->u.allowed.label, data->label_map_data);
else
new_r->u.allowed.label = NULL_TREE;
break;
case ERT_MUST_NOT_THROW:
......
......@@ -942,6 +942,7 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
}
break;
case GIMPLE_NOP:
case GIMPLE_PREDICT:
break;
......
......@@ -1692,6 +1692,7 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
}
break;
case GIMPLE_NOP:
case GIMPLE_PREDICT:
break;
......
......@@ -323,8 +323,10 @@ lto_symtab_register_decl (tree decl,
&& (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL)
&& DECL_ASSEMBLER_NAME_SET_P (decl));
if (TREE_CODE (decl) == VAR_DECL)
gcc_assert (!(DECL_EXTERNAL (decl) && DECL_INITIAL (decl)));
if (TREE_CODE (decl) == VAR_DECL
&& DECL_INITIAL (decl))
gcc_assert (!DECL_EXTERNAL (decl)
|| (TREE_STATIC (decl) && TREE_READONLY (decl)));
if (TREE_CODE (decl) == FUNCTION_DECL)
gcc_assert (!DECL_ABSTRACT (decl));
......
......@@ -683,7 +683,6 @@ init_optimization_passes (void)
p = &all_lowering_passes;
NEXT_PASS (pass_warn_unused_result);
NEXT_PASS (pass_diagnose_omp_blocks);
NEXT_PASS (pass_remove_useless_stmts);
NEXT_PASS (pass_mudflap_1);
NEXT_PASS (pass_lower_omp);
NEXT_PASS (pass_lower_cf);
......
2009-10-08 Michael Matz <matz@suse.de>
PR middle-end/41573
* gcc.dg/tree-ssa/foldstring-1.c: Use fre dump.
* gcc.dg/tree-ssa/useless-1.c: Use gimple dump.
* gcc.dg/pr41573.c: New test.
2009-10-07 Joseph Myers <joseph@codesourcery.com>
PR c/41182
......
/* { dg-do compile } */
/* { dg-options "-O2" } */
__inline __attribute__ ((__always_inline__)) char *
strcpy (char *__dest, __const char *__src)
{
return __builtin___strcpy_chk (__dest, __src, __builtin_object_size (__dest, 2 > 1));
}
const char* get_attr(unsigned attr)
{
static char tmp[256];
strcpy(tmp, "");
return tmp;
}
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-useless" } */
/* { dg-options "-O1 -fdump-tree-fre" } */
void
arf ()
......@@ -7,5 +7,5 @@ arf ()
if (""[0] == 0)
blah ();
}
/* { dg-final { scan-tree-dump-times "= 0;" 1 "useless"} } */
/* { dg-final { cleanup-tree-dump "useless" } } */
/* { dg-final { scan-tree-dump-times "= 0;" 1 "fre"} } */
/* { dg-final { cleanup-tree-dump "fre" } } */
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-useless" } */
/* { dg-options "-O1 -fdump-tree-gimple" } */
void
foo (void)
......@@ -13,5 +13,5 @@ foo (void)
in the loop exit condition, it would be re-introduced during
GIMPLE lowering, at the cost of an extra statement, label,
and basic block. */
/* { dg-final { scan-tree-dump-times "goto" 3 "useless"} } */
/* { dg-final { cleanup-tree-dump "useless" } } */
/* { dg-final { scan-tree-dump-times "goto" 3 "gimple"} } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
......@@ -1715,423 +1715,6 @@ single_noncomplex_succ (basic_block bb)
return bb;
}
/* Walk the function tree removing unnecessary statements.
* Empty statement nodes are removed
* Unnecessary TRY_FINALLY and TRY_CATCH blocks are removed
* Unnecessary COND_EXPRs are removed
* Some unnecessary BIND_EXPRs are removed
* GOTO_EXPRs immediately preceding destination are removed.
Clearly more work could be done. The trick is doing the analysis
and removal fast enough to be a net improvement in compile times.
Note that when we remove a control structure such as a COND_EXPR
BIND_EXPR, or TRY block, we will need to repeat this optimization pass
to ensure we eliminate all the useless code. */
struct rus_data
{
bool repeat;
bool may_throw;
bool may_branch;
bool has_label;
bool last_was_goto;
gimple_stmt_iterator last_goto_gsi;
};
static void remove_useless_stmts_1 (gimple_stmt_iterator *gsi, struct rus_data *);
/* Given a statement sequence, find the first executable statement with
location information, and warn that it is unreachable. When searching,
descend into containers in execution order. */
static bool
remove_useless_stmts_warn_notreached (gimple_seq stmts)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
if (gimple_no_warning_p (stmt)) return false;
if (gimple_has_location (stmt))
{
location_t loc = gimple_location (stmt);
if (LOCATION_LINE (loc) > 0)
{
warning_at (loc, OPT_Wunreachable_code, "will never be executed");
return true;
}
}
switch (gimple_code (stmt))
{
/* Unfortunately, we need the CFG now to detect unreachable
branches in a conditional, so conditionals are not handled here. */
case GIMPLE_TRY:
if (remove_useless_stmts_warn_notreached (gimple_try_eval (stmt)))
return true;
if (remove_useless_stmts_warn_notreached (gimple_try_cleanup (stmt)))
return true;
break;
case GIMPLE_CATCH:
return remove_useless_stmts_warn_notreached (gimple_catch_handler (stmt));
case GIMPLE_EH_FILTER:
return remove_useless_stmts_warn_notreached (gimple_eh_filter_failure (stmt));
case GIMPLE_BIND:
return remove_useless_stmts_warn_notreached (gimple_bind_body (stmt));
default:
break;
}
}
return false;
}
/* Helper for remove_useless_stmts_1. Handle GIMPLE_COND statements. */
static void
remove_useless_stmts_cond (gimple_stmt_iterator *gsi, struct rus_data *data)
{
gimple stmt = gsi_stmt (*gsi);
/* The folded result must still be a conditional statement. */
fold_stmt (gsi);
gcc_assert (gsi_stmt (*gsi) == stmt);
data->may_branch = true;
/* Replace trivial conditionals with gotos. */
if (gimple_cond_true_p (stmt))
{
/* Goto THEN label. */
tree then_label = gimple_cond_true_label (stmt);
gsi_replace (gsi, gimple_build_goto (then_label), false);
data->last_goto_gsi = *gsi;
data->last_was_goto = true;
data->repeat = true;
}
else if (gimple_cond_false_p (stmt))
{
/* Goto ELSE label. */
tree else_label = gimple_cond_false_label (stmt);
gsi_replace (gsi, gimple_build_goto (else_label), false);
data->last_goto_gsi = *gsi;
data->last_was_goto = true;
data->repeat = true;
}
else
{
tree then_label = gimple_cond_true_label (stmt);
tree else_label = gimple_cond_false_label (stmt);
if (then_label == else_label)
{
/* Goto common destination. */
gsi_replace (gsi, gimple_build_goto (then_label), false);
data->last_goto_gsi = *gsi;
data->last_was_goto = true;
data->repeat = true;
}
}
gsi_next (gsi);
data->last_was_goto = false;
}
/* Helper for remove_useless_stmts_1.
Handle the try-finally case for GIMPLE_TRY statements. */
static void
remove_useless_stmts_tf (gimple_stmt_iterator *gsi, struct rus_data *data)
{
bool save_may_branch, save_may_throw;
bool this_may_branch, this_may_throw;
gimple_seq eval_seq, cleanup_seq;
gimple_stmt_iterator eval_gsi, cleanup_gsi;
gimple stmt = gsi_stmt (*gsi);
/* Collect may_branch and may_throw information for the body only. */
save_may_branch = data->may_branch;
save_may_throw = data->may_throw;
data->may_branch = false;
data->may_throw = false;
data->last_was_goto = false;
eval_seq = gimple_try_eval (stmt);
eval_gsi = gsi_start (eval_seq);
remove_useless_stmts_1 (&eval_gsi, data);
this_may_branch = data->may_branch;
this_may_throw = data->may_throw;
data->may_branch |= save_may_branch;
data->may_throw |= save_may_throw;
data->last_was_goto = false;
cleanup_seq = gimple_try_cleanup (stmt);
cleanup_gsi = gsi_start (cleanup_seq);
remove_useless_stmts_1 (&cleanup_gsi, data);
/* If the body is empty, then we can emit the FINALLY block without
the enclosing TRY_FINALLY_EXPR. */
if (gimple_seq_empty_p (eval_seq))
{
gsi_insert_seq_before (gsi, cleanup_seq, GSI_SAME_STMT);
gsi_remove (gsi, false);
data->repeat = true;
}
/* If the handler is empty, then we can emit the TRY block without
the enclosing TRY_FINALLY_EXPR. */
else if (gimple_seq_empty_p (cleanup_seq))
{
gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
gsi_remove (gsi, false);
data->repeat = true;
}
/* If the body neither throws, nor branches, then we can safely
string the TRY and FINALLY blocks together. */
else if (!this_may_branch && !this_may_throw)
{
gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
gsi_insert_seq_before (gsi, cleanup_seq, GSI_SAME_STMT);
gsi_remove (gsi, false);
data->repeat = true;
}
else
gsi_next (gsi);
}
/* Helper for remove_useless_stmts_1.
Handle the try-catch case for GIMPLE_TRY statements. */
static void
remove_useless_stmts_tc (gimple_stmt_iterator *gsi, struct rus_data *data)
{
bool save_may_throw, this_may_throw;
gimple_seq eval_seq, cleanup_seq, handler_seq, failure_seq;
gimple_stmt_iterator eval_gsi, cleanup_gsi, handler_gsi, failure_gsi;
gimple stmt = gsi_stmt (*gsi);
/* Collect may_throw information for the body only. */
save_may_throw = data->may_throw;
data->may_throw = false;
data->last_was_goto = false;
eval_seq = gimple_try_eval (stmt);
eval_gsi = gsi_start (eval_seq);
remove_useless_stmts_1 (&eval_gsi, data);
this_may_throw = data->may_throw;
data->may_throw = save_may_throw;
cleanup_seq = gimple_try_cleanup (stmt);
/* If the body cannot throw, then we can drop the entire TRY_CATCH_EXPR. */
if (!this_may_throw)
{
if (warn_notreached)
{
remove_useless_stmts_warn_notreached (cleanup_seq);
}
gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
gsi_remove (gsi, false);
data->repeat = true;
return;
}
/* Process the catch clause specially. We may be able to tell that
no exceptions propagate past this point. */
this_may_throw = true;
cleanup_gsi = gsi_start (cleanup_seq);
stmt = gsi_stmt (cleanup_gsi);
data->last_was_goto = false;
switch (gimple_code (stmt))
{
case GIMPLE_CATCH:
/* If the first element is a catch, they all must be. */
while (!gsi_end_p (cleanup_gsi))
{
stmt = gsi_stmt (cleanup_gsi);
/* If we catch all exceptions, then the body does not
propagate exceptions past this point. */
if (gimple_catch_types (stmt) == NULL)
this_may_throw = false;
data->last_was_goto = false;
handler_seq = gimple_catch_handler (stmt);
handler_gsi = gsi_start (handler_seq);
remove_useless_stmts_1 (&handler_gsi, data);
gsi_next (&cleanup_gsi);
}
gsi_next (gsi);
break;
case GIMPLE_EH_FILTER:
if (gimple_eh_filter_types (stmt) == NULL)
this_may_throw = false;
failure_seq = gimple_eh_filter_failure (stmt);
failure_gsi = gsi_start (failure_seq);
remove_useless_stmts_1 (&failure_gsi, data);
gsi_next (gsi);
break;
case GIMPLE_EH_MUST_NOT_THROW:
this_may_throw = false;
gsi_next (gsi);
break;
default:
/* Otherwise this is a list of cleanup statements. */
remove_useless_stmts_1 (&cleanup_gsi, data);
/* If the cleanup is empty, then we can emit the TRY block without
the enclosing TRY_CATCH_EXPR. */
if (gimple_seq_empty_p (cleanup_seq))
{
gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
gsi_remove(gsi, false);
data->repeat = true;
}
else
gsi_next (gsi);
break;
}
data->may_throw |= this_may_throw;
}
/* Helper for remove_useless_stmts_1. Handle GIMPLE_BIND statements. */
static void
remove_useless_stmts_bind (gimple_stmt_iterator *gsi, struct rus_data *data ATTRIBUTE_UNUSED)
{
tree block;
gimple_seq body_seq, fn_body_seq;
gimple_stmt_iterator body_gsi;
gimple stmt = gsi_stmt (*gsi);
/* First remove anything underneath the BIND_EXPR. */
body_seq = gimple_bind_body (stmt);
body_gsi = gsi_start (body_seq);
remove_useless_stmts_1 (&body_gsi, data);
/* If the GIMPLE_BIND has no variables, then we can pull everything
up one level and remove the GIMPLE_BIND, unless this is the toplevel
GIMPLE_BIND for the current function or an inlined function.
When this situation occurs we will want to apply this
optimization again. */
block = gimple_bind_block (stmt);
fn_body_seq = gimple_body (current_function_decl);
if (gimple_bind_vars (stmt) == NULL_TREE
&& (gimple_seq_empty_p (fn_body_seq)
|| stmt != gimple_seq_first_stmt (fn_body_seq))
&& (! block
|| ! BLOCK_ABSTRACT_ORIGIN (block)
|| (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
!= FUNCTION_DECL)))
{
tree var = NULL_TREE;
/* Even if there are no gimple_bind_vars, there might be other
decls in BLOCK_VARS rendering the GIMPLE_BIND not useless. */
if (block && !BLOCK_NUM_NONLOCALIZED_VARS (block))
for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
if (TREE_CODE (var) == IMPORTED_DECL)
break;
if (var || (block && BLOCK_NUM_NONLOCALIZED_VARS (block)))
gsi_next (gsi);
else
{
gsi_insert_seq_before (gsi, body_seq, GSI_SAME_STMT);
gsi_remove (gsi, false);
data->repeat = true;
}
}
else
gsi_next (gsi);
}
/* Helper for remove_useless_stmts_1. Handle GIMPLE_GOTO statements. */
static void
remove_useless_stmts_goto (gimple_stmt_iterator *gsi, struct rus_data *data)
{
gimple stmt = gsi_stmt (*gsi);
tree dest = gimple_goto_dest (stmt);
data->may_branch = true;
data->last_was_goto = false;
/* Record iterator for last goto expr, so that we can delete it if unnecessary. */
if (TREE_CODE (dest) == LABEL_DECL)
{
data->last_goto_gsi = *gsi;
data->last_was_goto = true;
}
gsi_next(gsi);
}
/* Helper for remove_useless_stmts_1. Handle GIMPLE_LABEL statements. */
static void
remove_useless_stmts_label (gimple_stmt_iterator *gsi, struct rus_data *data)
{
gimple stmt = gsi_stmt (*gsi);
tree label = gimple_label_label (stmt);
data->has_label = true;
/* We do want to jump across non-local label receiver code. */
if (DECL_NONLOCAL (label))
data->last_was_goto = false;
else if (data->last_was_goto
&& gimple_goto_dest (gsi_stmt (data->last_goto_gsi)) == label)
{
/* Replace the preceding GIMPLE_GOTO statement with
a GIMPLE_NOP, which will be subsequently removed.
In this way, we avoid invalidating other iterators
active on the statement sequence. */
gsi_replace(&data->last_goto_gsi, gimple_build_nop(), false);
data->last_was_goto = false;
data->repeat = true;
}
/* ??? Add something here to delete unused labels. */
gsi_next (gsi);
}
/* T is CALL_EXPR. Set current_function_calls_* flags. */
void
......@@ -2156,188 +1739,6 @@ clear_special_calls (void)
cfun->calls_setjmp = false;
}
/* Remove useless statements from a statement sequence, and perform
some preliminary simplifications. */
static void
remove_useless_stmts_1 (gimple_stmt_iterator *gsi, struct rus_data *data)
{
while (!gsi_end_p (*gsi))
{
gimple stmt = gsi_stmt (*gsi);
switch (gimple_code (stmt))
{
case GIMPLE_COND:
remove_useless_stmts_cond (gsi, data);
break;
case GIMPLE_GOTO:
remove_useless_stmts_goto (gsi, data);
break;
case GIMPLE_LABEL:
remove_useless_stmts_label (gsi, data);
break;
case GIMPLE_ASSIGN:
fold_stmt (gsi);
stmt = gsi_stmt (*gsi);
data->last_was_goto = false;
if (stmt_could_throw_p (stmt))
data->may_throw = true;
gsi_next (gsi);
break;
case GIMPLE_ASM:
fold_stmt (gsi);
data->last_was_goto = false;
gsi_next (gsi);
break;
case GIMPLE_CALL:
fold_stmt (gsi);
stmt = gsi_stmt (*gsi);
data->last_was_goto = false;
if (is_gimple_call (stmt))
notice_special_calls (stmt);
/* We used to call update_gimple_call_flags here,
which copied side-effects and nothrows status
from the function decl to the call. In the new
tuplified GIMPLE, the accessors for this information
always consult the function decl, so this copying
is no longer necessary. */
if (stmt_could_throw_p (stmt))
data->may_throw = true;
gsi_next (gsi);
break;
case GIMPLE_RETURN:
fold_stmt (gsi);
data->last_was_goto = false;
data->may_branch = true;
gsi_next (gsi);
break;
case GIMPLE_BIND:
remove_useless_stmts_bind (gsi, data);
break;
case GIMPLE_TRY:
if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH)
remove_useless_stmts_tc (gsi, data);
else if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
remove_useless_stmts_tf (gsi, data);
else
gcc_unreachable ();
break;
case GIMPLE_CATCH:
gcc_unreachable ();
break;
case GIMPLE_NOP:
gsi_remove (gsi, false);
break;
case GIMPLE_OMP_FOR:
{
gimple_seq pre_body_seq = gimple_omp_for_pre_body (stmt);
gimple_stmt_iterator pre_body_gsi = gsi_start (pre_body_seq);
remove_useless_stmts_1 (&pre_body_gsi, data);
data->last_was_goto = false;
}
/* FALLTHROUGH */
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_CONTINUE:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
{
gimple_seq body_seq = gimple_omp_body (stmt);
gimple_stmt_iterator body_gsi = gsi_start (body_seq);
remove_useless_stmts_1 (&body_gsi, data);
data->last_was_goto = false;
gsi_next (gsi);
}
break;
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
{
/* Make sure the outermost GIMPLE_BIND isn't removed
as useless. */
gimple_seq body_seq = gimple_omp_body (stmt);
gimple bind = gimple_seq_first_stmt (body_seq);
gimple_seq bind_seq = gimple_bind_body (bind);
gimple_stmt_iterator bind_gsi = gsi_start (bind_seq);
remove_useless_stmts_1 (&bind_gsi, data);
data->last_was_goto = false;
gsi_next (gsi);
}
break;
default:
data->last_was_goto = false;
gsi_next (gsi);
break;
}
}
}
/* Walk the function tree, removing useless statements and performing
some preliminary simplifications. */
static unsigned int
remove_useless_stmts (void)
{
struct rus_data data;
clear_special_calls ();
do
{
gimple_stmt_iterator gsi;
gsi = gsi_start (gimple_body (current_function_decl));
memset (&data, 0, sizeof (data));
remove_useless_stmts_1 (&gsi, &data);
}
while (data.repeat);
#ifdef ENABLE_TYPES_CHECKING
verify_types_in_gimple_seq (gimple_body (current_function_decl));
#endif
return 0;
}
struct gimple_opt_pass pass_remove_useless_stmts =
{
{
GIMPLE_PASS,
"useless", /* name */
NULL, /* gate */
remove_useless_stmts, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
TV_NONE, /* tv_id */
PROP_gimple_any, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func /* todo_flags_finish */
}
};
/* Remove PHI nodes associated with basic block BB and all edges out of BB. */
static void
......
......@@ -1919,6 +1919,12 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
else
{
x = gimple_seq_first_stmt (gimple_try_cleanup (stmt));
if (!x)
{
replace = gimple_try_eval (stmt);
lower_eh_constructs_1 (state, replace);
}
else
switch (gimple_code (x))
{
case GIMPLE_CATCH:
......
......@@ -333,7 +333,6 @@ extern void tree_lowering_passes (tree decl);
extern struct gimple_opt_pass pass_mudflap_1;
extern struct gimple_opt_pass pass_mudflap_2;
extern struct gimple_opt_pass pass_remove_useless_stmts;
extern struct gimple_opt_pass pass_lower_cf;
extern struct gimple_opt_pass pass_refactor_eh;
extern struct gimple_opt_pass pass_lower_eh;
......
......@@ -4438,7 +4438,8 @@ free_lang_data_in_decl (tree decl)
&& !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
if (DECL_EXTERNAL (decl))
if (DECL_EXTERNAL (decl)
&& (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
DECL_INITIAL (decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == TYPE_DECL)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment