diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc index 08876bfc1c7..09bbfaca22e 100644 --- a/gcc/tree-ssa-dce.cc +++ b/gcc/tree-ssa-dce.cc @@ -191,14 +191,35 @@ mark_operand_necessary (tree op) } +/* Called via walk_tree, look for DEBUG_EXPR_DECLs and mark them in DATA. */ + +static tree +find_debug_expr_decl (tree *tp, int *walk_subtrees, void *data) +{ + auto_bitmap *decls = (auto_bitmap *) data; + + if (TREE_CODE (*tp) == SSA_NAME || IS_TYPE_OR_DECL_P (*tp)) + { + if (TREE_CODE (*tp) == DEBUG_EXPR_DECL) + bitmap_set_bit (*decls, DECL_UID (*tp)); + + *walk_subtrees = 0; + } + + return NULL_TREE; +} + /* Mark STMT as necessary if it obviously is. Add it to the worklist if it can make other statements necessary. + If STMT is a DEBUG_BIND, mark the necessary DEBUG_EXPR_DECLs in DECLS. + If AGGRESSIVE is false, control statements are conservatively marked as necessary. */ static void -mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) +mark_stmt_if_obviously_necessary (gimple *stmt, auto_bitmap *decls, + bool aggressive) { /* Statements that are implicitly live. Most function calls, asm and return statements are required. Labels and GIMPLE_BIND nodes @@ -258,14 +279,28 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) } case GIMPLE_DEBUG: - /* Debug temps without a value are not useful. ??? If we could - easily locate the debug temp bind stmt for a use thereof, - would could refrain from marking all debug temps here, and - mark them only if they're used. */ - if (gimple_debug_nonbind_marker_p (stmt) - || !gimple_debug_bind_p (stmt) - || gimple_debug_bind_has_value_p (stmt) - || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL) + if (gimple_debug_bind_p (stmt)) + { + tree var = gimple_debug_bind_get_var (stmt); + tree val = gimple_debug_bind_get_value (stmt); + bool necessary = false; + + /* A bind statement for a real variable is always necessary. */ + if (TREE_CODE (var) != DEBUG_EXPR_DECL) + necessary = true; + + /* A bind statement with a value is necessary for now and we look + into the value to find out necessary DEBUG_EXPR_DECLs. */ + if (val) + { + walk_tree (&val, find_debug_expr_decl, decls, NULL); + necessary = true; + } + + if (necessary ) + mark_stmt_necessary (stmt, false); + } + else mark_stmt_necessary (stmt, false); return; @@ -398,6 +433,7 @@ find_obviously_necessary_stmts (bool aggressive) gimple_stmt_iterator gsi; edge e; gimple *phi, *stmt; + auto_bitmap necessary_decls; int flags; FOR_EACH_BB_FN (bb, cfun) @@ -414,10 +450,35 @@ find_obviously_necessary_stmts (bool aggressive) { stmt = gsi_stmt (gsi); gimple_set_plf (stmt, STMT_NECESSARY, false); - mark_stmt_if_obviously_necessary (stmt, aggressive); + mark_stmt_if_obviously_necessary (stmt, &necessary_decls, aggressive); } } + /* Check all debug bind statements again in the basic blocks and find out + those which set an unnecessary DEBUG_EXPR_DECL to a value. */ + if (MAY_HAVE_DEBUG_BIND_STMTS) + FOR_EACH_BB_FN (bb, cfun) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + stmt = gsi_stmt (gsi); + if (gimple_debug_bind_p (stmt) + && gimple_debug_bind_has_value_p (stmt)) + { + tree var = gimple_debug_bind_get_var (stmt); + if (TREE_CODE (var) == DEBUG_EXPR_DECL + && !bitmap_bit_p (necessary_decls, DECL_UID (var))) + { + gimple_set_plf (stmt, STMT_NECESSARY, false); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Unmarking useful stmt: "); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); + fprintf (dump_file, "\n"); + } + } + } + } + /* Pure and const functions are finite and thus have no infinite loops in them. */ flags = flags_from_decl_or_type (current_function_decl);