diff options
Diffstat (limited to 'gcc/tree-parloops.c')
-rw-r--r-- | gcc/tree-parloops.c | 94 |
1 files changed, 91 insertions, 3 deletions
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 9b9ac758dc2..a6d8f215914 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -508,7 +508,11 @@ eliminate_local_variables_stmt (edge entry, gimple stmt, dta.decl_address = decl_address; dta.changed = false; - walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info); + if (gimple_debug_bind_p (stmt)) + walk_tree (gimple_debug_bind_get_value_ptr (stmt), + eliminate_local_variables_1, &dta.info, NULL); + else + walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info); if (dta.changed) update_stmt (stmt); @@ -692,6 +696,53 @@ separate_decls_in_region_stmt (edge entry, edge exit, gimple stmt, } } +/* Finds the ssa names used in STMT that are defined outside the + region between ENTRY and EXIT and replaces such ssa names with + their duplicates. The duplicates are stored to NAME_COPIES. Base + decls of all ssa names used in STMT (including those defined in + LOOP) are replaced with the new temporary variables; the + replacement decls are stored in DECL_COPIES. */ + +static bool +separate_decls_in_region_debug_bind (gimple stmt, + htab_t name_copies, htab_t decl_copies) +{ + use_operand_p use; + ssa_op_iter oi; + tree var, name; + struct int_tree_map ielt; + struct name_to_copy_elt elt; + void **slot, **dslot; + + var = gimple_debug_bind_get_var (stmt); + gcc_assert (DECL_P (var) && SSA_VAR_P (var)); + ielt.uid = DECL_UID (var); + dslot = htab_find_slot_with_hash (decl_copies, &ielt, ielt.uid, NO_INSERT); + if (!dslot) + return true; + gimple_debug_bind_set_var (stmt, ((struct int_tree_map *) *dslot)->to); + + FOR_EACH_PHI_OR_STMT_USE (use, stmt, oi, SSA_OP_USE) + { + name = USE_FROM_PTR (use); + if (TREE_CODE (name) != SSA_NAME) + continue; + + elt.version = SSA_NAME_VERSION (name); + slot = htab_find_slot_with_hash (name_copies, &elt, elt.version, NO_INSERT); + if (!slot) + { + gimple_debug_bind_reset_value (stmt); + update_stmt (stmt); + break; + } + + SET_USE (use, ((struct name_to_copy_elt *) *slot)->new_name); + } + + return false; +} + /* Callback for htab_traverse. Adds a field corresponding to the reduction specified in SLOT. The type is passed in DATA. */ @@ -1027,6 +1078,7 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list, basic_block bb; basic_block entry_bb = bb1; basic_block exit_bb = exit->dest; + bool has_debug_stmt = false; entry = single_succ_edge (entry_bb); gather_blocks_in_sese_region (entry_bb, exit_bb, &body); @@ -1040,11 +1092,47 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list, name_copies, decl_copies); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - separate_decls_in_region_stmt (entry, exit, gsi_stmt (gsi), - name_copies, decl_copies); + { + gimple stmt = gsi_stmt (gsi); + + if (is_gimple_debug (stmt)) + has_debug_stmt = true; + else + separate_decls_in_region_stmt (entry, exit, stmt, + name_copies, decl_copies); + } } } + /* Now process debug bind stmts. We must not create decls while + processing debug stmts, so we defer their processing so as to + make sure we will have debug info for as many variables as + possible (all of those that were dealt with in the loop above), + and discard those for which we know there's nothing we can + do. */ + if (has_debug_stmt) + for (i = 0; VEC_iterate (basic_block, body, i, bb); i++) + if (bb != entry_bb && bb != exit_bb) + { + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) + { + gimple stmt = gsi_stmt (gsi); + + if (gimple_debug_bind_p (stmt)) + { + if (separate_decls_in_region_debug_bind (stmt, + name_copies, + decl_copies)) + { + gsi_remove (&gsi, true); + continue; + } + } + + gsi_next (&gsi); + } + } + VEC_free (basic_block, heap, body); if (htab_elements (name_copies) == 0 && reduction_list == 0) |