diff options
-rw-r--r-- | gcc/ChangeLog | 31 | ||||
-rw-r--r-- | gcc/omp-low.c | 79 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 115 | ||||
-rw-r--r-- | gcc/tree-flow.h | 4 | ||||
-rw-r--r-- | libgomp/ChangeLog | 5 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c/debug-1.c | 162 |
6 files changed, 349 insertions, 47 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f1279f8b7af..38ce1cff594 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2008-06-27 Jakub Jelinek <jakub@redhat.com> + + PR debug/36617 + * tree-cfg.c (struct move_stmt_d): Replace block field with + orig_block and new_block fields. + (move_stmt_r): Only set TREE_BLOCK to p->new_block if + if it used to be NULL, p->orig_block or if p->orig_block is NULL. + (move_block_to_fn): Replace vars_map and new_label_map arguments + with struct move_stmt_d pointer. + (replace_block_vars_by_duplicates): New function. + (move_sese_region_to_fn): Add ORIG_BLOCK argument. Adjust + move_block_to_fn caller. If ORIG_BLOCK is non-NULL, move over + all subblocks of ORIG_BLOCK to the new function. Call + replace_block_vars_by_duplicates. + * tree-flow.h (move_sese_region_to_fn): Adjust prototype. + * omp-low.c (expand_omp_taskreg): Set TREE_USED on DECL_INITIAL + BLOCK of the new function. Adjust move_sese_region_to_fn caller. + Prune vars with original DECL_CONTEXT from child_cfun->local_decls. + (expand_omp): Temporarily set input_location to the location of + region's controlling stmt. + (lower_omp_sections, lower_omp_for): Add a BLOCK into outermost + BIND_EXPR, push ctx->block_vars and gimplification vars into + the BIND_EXPR and its block's BLOCK_VARS instead of directly + into dest function. + (lower_omp_single): Set TREE_USED on the BIND_EXPR's BLOCK if + there are any BLOCK_VARS. + (lower_omp_taskreg): Set BLOCK on a BIND_EXPR containing the + OMP_PARALLEL or OMP_TASK stmt. + (lower_omp): Save and restore input_location around the lower_omp_1 + call. + 2008-06-27 Richard Guenther <rguenther@suse.de> PR tree-optimization/36400 diff --git a/gcc/omp-low.c b/gcc/omp-low.c index e26ebbcb9d7..e5680077bd0 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3140,7 +3140,7 @@ expand_omp_taskreg (struct omp_region *region) { basic_block entry_bb, exit_bb, new_bb; struct function *child_cfun; - tree child_fn, block, t, ws_args; + tree child_fn, block, t, ws_args, *tp; block_stmt_iterator si; tree entry_stmt; edge e; @@ -3251,6 +3251,7 @@ expand_omp_taskreg (struct omp_region *region) block = DECL_INITIAL (child_fn); BLOCK_VARS (block) = list2chain (child_cfun->local_decls); DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb)); + TREE_USED (block) = 1; /* Reset DECL_CONTEXT on function arguments. */ for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t)) @@ -3287,11 +3288,22 @@ expand_omp_taskreg (struct omp_region *region) init_ssa_operands (); cfun->gimple_df->in_ssa_p = true; pop_cfun (); + block = NULL_TREE; } - new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb); + else + block = TREE_BLOCK (entry_stmt); + + new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block); if (exit_bb) single_succ_edge (new_bb)->flags = EDGE_FALLTHRU; + /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */ + for (tp = &child_cfun->local_decls; *tp; ) + if (DECL_CONTEXT (TREE_VALUE (*tp)) != cfun->decl) + tp = &TREE_CHAIN (*tp); + else + *tp = TREE_CHAIN (*tp); + /* Inform the callgraph about the new function. */ DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties; @@ -5030,6 +5042,8 @@ expand_omp (struct omp_region *region) { while (region) { + location_t saved_location; + /* First, determine whether this is a combined parallel+workshare region. */ if (region->type == OMP_PARALLEL) @@ -5038,6 +5052,10 @@ expand_omp (struct omp_region *region) if (region->inner) expand_omp (region->inner); + saved_location = input_location; + if (EXPR_HAS_LOCATION (last_stmt (region->entry))) + input_location = EXPR_LOCATION (last_stmt (region->entry)); + switch (region->type) { case OMP_PARALLEL: @@ -5075,11 +5093,11 @@ expand_omp (struct omp_region *region) expand_omp_atomic (region); break; - default: gcc_unreachable (); } + input_location = saved_location; region = region->next; } } @@ -5312,12 +5330,18 @@ lower_omp_sections (tree *stmt_p, omp_context *ctx) olist = NULL_TREE; lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx); - pop_gimplify_context (NULL_TREE); - record_vars_into (ctx->block_vars, ctx->cb.dst_fn); - - new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); + block = make_node (BLOCK); + new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, block); TREE_SIDE_EFFECTS (new_stmt) = 1; + pop_gimplify_context (new_stmt); + + BIND_EXPR_VARS (new_stmt) + = chainon (BIND_EXPR_VARS (new_stmt), ctx->block_vars); + BLOCK_VARS (block) = BIND_EXPR_VARS (new_stmt); + if (BLOCK_VARS (block)) + TREE_USED (block) = 1; + new_body = alloc_stmt_list (); append_to_statement_list (ilist, &new_body); append_to_statement_list (stmt, &new_body); @@ -5491,6 +5515,8 @@ lower_omp_single (tree *stmt_p, omp_context *ctx) BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); BLOCK_VARS (block) = BIND_EXPR_VARS (bind); + if (BLOCK_VARS (block)) + TREE_USED (block) = 1; } @@ -5714,7 +5740,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p, static void lower_omp_for (tree *stmt_p, omp_context *ctx) { - tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p; + tree t, stmt, ilist, dlist, new_stmt, block, *body_p, *rhs_p; struct omp_for_data fd; int i; @@ -5725,14 +5751,17 @@ lower_omp_for (tree *stmt_p, omp_context *ctx) lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx); lower_omp (&OMP_FOR_BODY (stmt), ctx); + block = make_node (BLOCK); + new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, block); + TREE_SIDE_EFFECTS (new_stmt) = 1; + body_p = &BIND_EXPR_BODY (new_stmt); + /* Move declaration of temporaries in the loop body before we make it go away. */ if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR) - record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn); - - new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); - TREE_SIDE_EFFECTS (new_stmt) = 1; - body_p = &BIND_EXPR_BODY (new_stmt); + BIND_EXPR_VARS (new_stmt) + = chainon (BIND_EXPR_VARS (new_stmt), + BIND_EXPR_VARS (OMP_FOR_BODY (stmt))); /* The pre-body and input clauses go before the lowered OMP_FOR. */ ilist = NULL; @@ -5786,8 +5815,12 @@ lower_omp_for (tree *stmt_p, omp_context *ctx) OMP_RETURN_NOWAIT (t) = fd.have_nowait; append_to_statement_list (t, body_p); - pop_gimplify_context (NULL_TREE); - record_vars_into (ctx->block_vars, ctx->cb.dst_fn); + pop_gimplify_context (new_stmt); + BIND_EXPR_VARS (new_stmt) + = chainon (BIND_EXPR_VARS (new_stmt), ctx->block_vars); + BLOCK_VARS (block) = BIND_EXPR_VARS (new_stmt); + if (BLOCK_VARS (block)) + TREE_USED (block) = 1; OMP_FOR_BODY (stmt) = NULL_TREE; OMP_FOR_PRE_BODY (stmt) = NULL_TREE; @@ -6157,8 +6190,9 @@ lower_omp_taskreg (tree *stmt_p, omp_context *ctx) /* Once all the expansions are done, sequence all the different fragments inside OMP_TASKREG_BODY. */ - bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); - append_to_statement_list (ilist, &BIND_EXPR_BODY (bind)); + bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, + BIND_EXPR_BLOCK (par_bind)); + TREE_SIDE_EFFECTS (bind) = 1; new_body = alloc_stmt_list (); @@ -6180,7 +6214,14 @@ lower_omp_taskreg (tree *stmt_p, omp_context *ctx) OMP_TASKREG_BODY (stmt) = new_body; append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); - append_to_statement_list (olist, &BIND_EXPR_BODY (bind)); + if (ilist || olist) + { + append_to_statement_list (bind, &ilist); + append_to_statement_list (olist, &ilist); + bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + append_to_statement_list (ilist, &BIND_EXPR_BODY (bind)); + } *stmt_p = bind; @@ -6363,7 +6404,9 @@ lower_omp_1 (tree *tp, omp_context *ctx, tree_stmt_iterator *tsi) static void lower_omp (tree *stmt_p, omp_context *ctx) { + location_t saved_location = input_location; lower_omp_1 (stmt_p, ctx, NULL); + input_location = saved_location; } /* Main entry point. */ diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 50f53a080e8..341a1de749d 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -5665,7 +5665,8 @@ replace_ssa_name (tree name, struct pointer_map_t *vars_map, struct move_stmt_d { - tree block; + tree orig_block; + tree new_block; tree from_context; tree to_context; struct pointer_map_t *vars_map; @@ -5674,8 +5675,8 @@ struct move_stmt_d }; /* Helper for move_block_to_fn. Set TREE_BLOCK in every expression - contained in *TP and change the DECL_CONTEXT of every local - variable referenced in *TP. */ + contained in *TP if it has been ORIG_BLOCK previously and change the + DECL_CONTEXT of every local variable referenced in *TP. */ static tree move_stmt_r (tree *tp, int *walk_subtrees, void *data) @@ -5683,9 +5684,22 @@ move_stmt_r (tree *tp, int *walk_subtrees, void *data) struct move_stmt_d *p = (struct move_stmt_d *) data; tree t = *tp; - if (p->block - && (EXPR_P (t) || GIMPLE_STMT_P (t))) - TREE_BLOCK (t) = p->block; + if (EXPR_P (t) || GIMPLE_STMT_P (t)) + { + tree block = TREE_BLOCK (t); + if (p->orig_block == NULL_TREE + || block == p->orig_block + || block == NULL_TREE) + TREE_BLOCK (t) = p->new_block; +#ifdef ENABLE_CHECKING + else if (block != p->new_block) + { + while (block && block != p->orig_block) + block = BLOCK_SUPERCONTEXT (block); + gcc_assert (block); + } +#endif + } if (OMP_DIRECTIVE_P (t) && TREE_CODE (t) != OMP_RETURN @@ -5792,14 +5806,12 @@ mark_virtual_ops_in_region (VEC (basic_block,heap) *bbs) static void move_block_to_fn (struct function *dest_cfun, basic_block bb, basic_block after, bool update_edge_count_p, - struct pointer_map_t *vars_map, htab_t new_label_map, - int eh_offset) + struct move_stmt_d *d, int eh_offset) { struct control_flow_graph *cfg; edge_iterator ei; edge e; block_stmt_iterator si; - struct move_stmt_d d; unsigned old_len, new_len; tree phi, next_phi; @@ -5856,33 +5868,22 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, continue; } - SET_PHI_RESULT (phi, replace_ssa_name (op, vars_map, dest_cfun->decl)); + SET_PHI_RESULT (phi, + replace_ssa_name (op, d->vars_map, dest_cfun->decl)); FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE) { op = USE_FROM_PTR (use); if (TREE_CODE (op) == SSA_NAME) - SET_USE (use, replace_ssa_name (op, vars_map, dest_cfun->decl)); + SET_USE (use, replace_ssa_name (op, d->vars_map, dest_cfun->decl)); } } - /* The statements in BB need to be associated with a new TREE_BLOCK. - Labels need to be associated with a new label-to-block map. */ - memset (&d, 0, sizeof (d)); - d.vars_map = vars_map; - d.from_context = cfun->decl; - d.to_context = dest_cfun->decl; - d.new_label_map = new_label_map; - for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) { tree stmt = bsi_stmt (si); int region; - d.remap_decls_p = true; - if (TREE_BLOCK (stmt)) - d.block = DECL_INITIAL (dest_cfun->decl); - - walk_tree (&stmt, move_stmt_r, &d, NULL); + walk_tree (&stmt, move_stmt_r, d, NULL); if (TREE_CODE (stmt) == LABEL_EXPR) { @@ -5989,6 +5990,35 @@ new_label_mapper (tree decl, void *data) return m->to; } +/* Change DECL_CONTEXT of all BLOCK_VARS in block, including + subblocks. */ + +static void +replace_block_vars_by_duplicates (tree block, struct pointer_map_t *vars_map, + tree to_context) +{ + tree *tp, t; + + for (tp = &BLOCK_VARS (block); *tp; tp = &TREE_CHAIN (*tp)) + { + t = *tp; + replace_by_duplicate_decl (&t, vars_map, to_context); + if (t != *tp) + { + if (TREE_CODE (*tp) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*tp)) + { + SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (*tp)); + DECL_HAS_VALUE_EXPR_P (t) = 1; + } + TREE_CHAIN (t) = TREE_CHAIN (*tp); + *tp = t; + } + } + + for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block)) + replace_block_vars_by_duplicates (block, vars_map, to_context); +} + /* Move a single-entry, single-exit region delimited by ENTRY_BB and EXIT_BB to function DEST_CFUN. The whole region is replaced by a single basic block in the original CFG and the new basic block is @@ -5999,13 +6029,17 @@ new_label_mapper (tree decl, void *data) is that ENTRY_BB should be the only entry point and it must dominate EXIT_BB. + Change TREE_BLOCK of all statements in ORIG_BLOCK to the new + functions outermost BLOCK, move all subblocks of ORIG_BLOCK + to the new function. + All local variables referenced in the region are assumed to be in the corresponding BLOCK_VARS and unexpanded variable lists associated with DEST_CFUN. */ basic_block move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, - basic_block exit_bb) + basic_block exit_bb, tree orig_block) { VEC(basic_block,heap) *bbs, *dom_bbs; basic_block dom_entry = get_immediate_dominator (CDI_DOMINATORS, entry_bb); @@ -6019,6 +6053,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, htab_t new_label_map; struct pointer_map_t *vars_map; struct loop *loop = entry_bb->loop_father; + struct move_stmt_d d; /* If ENTRY does not strictly dominate EXIT, this cannot be an SESE region. */ @@ -6115,16 +6150,42 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, gcc_assert (VEC_length (basic_block, bbs) >= 2); after = dest_cfun->cfg->x_entry_block_ptr; vars_map = pointer_map_create (); + + memset (&d, 0, sizeof (d)); + d.vars_map = vars_map; + d.from_context = cfun->decl; + d.to_context = dest_cfun->decl; + d.new_label_map = new_label_map; + d.remap_decls_p = true; + d.orig_block = orig_block; + d.new_block = DECL_INITIAL (dest_cfun->decl); + for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++) { /* No need to update edge counts on the last block. It has already been updated earlier when we detached the region from the original CFG. */ - move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_map, - new_label_map, eh_offset); + move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, &d, eh_offset); after = bb; } + /* Rewire BLOCK_SUBBLOCKS of orig_block. */ + if (orig_block) + { + tree block; + gcc_assert (BLOCK_SUBBLOCKS (DECL_INITIAL (dest_cfun->decl)) + == NULL_TREE); + BLOCK_SUBBLOCKS (DECL_INITIAL (dest_cfun->decl)) + = BLOCK_SUBBLOCKS (orig_block); + for (block = BLOCK_SUBBLOCKS (orig_block); + block; block = BLOCK_CHAIN (block)) + BLOCK_SUPERCONTEXT (block) = DECL_INITIAL (dest_cfun->decl); + BLOCK_SUBBLOCKS (orig_block) = NULL_TREE; + } + + replace_block_vars_by_duplicates (DECL_INITIAL (dest_cfun->decl), + vars_map, dest_cfun->decl); + if (new_label_map) htab_delete (new_label_map); pointer_map_destroy (vars_map); diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 15329ac002e..ded7687b75e 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -1,5 +1,5 @@ /* Data and Control Flow Analysis for Trees. - Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007 + Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by Diego Novillo <dnovillo@redhat.com> @@ -788,7 +788,7 @@ extern void replace_uses_by (tree, tree); extern void start_recording_case_labels (void); extern void end_recording_case_labels (void); extern basic_block move_sese_region_to_fn (struct function *, basic_block, - basic_block); + basic_block, tree); void remove_edge_and_dominated_blocks (edge); void mark_virtual_ops_in_bb (basic_block); diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index ed27454354e..18e1bf7c43a 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,8 @@ +2008-06-27 Jakub Jelinek <jakub@redhat.com> + + PR debug/36617 + * testsuite/libgomp.c/debug-1.c: New test. + 2008-06-19 Jakub Jelinek <jakub@redhat.com> * testsuite/libgomp.c/nqueens-1.c: New test. diff --git a/libgomp/testsuite/libgomp.c/debug-1.c b/libgomp/testsuite/libgomp.c/debug-1.c new file mode 100644 index 00000000000..09bcf7f3cc1 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/debug-1.c @@ -0,0 +1,162 @@ +/* PR debug/36617 */ +/* { dg-do run } */ +/* { dg-options "-g -fopenmp -O0" } */ + +int +f1 (void) +{ + int v1i, v1j, v1k, v1l = 0; + v1i = 6; + v1j = 8; + #pragma omp parallel private (v1k) firstprivate (v1j) shared (v1i) reduction (+:v1l) + { + v1k = v1i + v1j; + { + int v1m = 1; + v1l = v1m; + } + } + return v1l; +} + +int v2k = 9; + +int +f2 (void) +{ + int v2i = 6, v2j = 7; + #pragma omp single private (v2i) firstprivate (v2k) + { + int v2l = v2j + v2k; + v2i = 8; + v2k = 10; + v2j = v2l + v2i; + } + return v2i + v2j; +} + +int +f3 (void) +{ + int v3i = 6, v3j = 7, v3k = 9; + #pragma omp parallel + { + #pragma omp master + v3i++; + #pragma omp single private (v3i) firstprivate (v3k) + { + int v3l = v3j + v3k; + v3i = 8; + v3k = 10; + v3j = v3l + v3i; + } + #pragma omp atomic + v3k++; + } + return v3i + v3j; +} + +int v4k = 9, v4l = 0; + +int +f4 (void) +{ + int v4i = 6, v4j = 7, v4n = 0; + #pragma omp sections private (v4i) firstprivate (v4k) reduction (+:v4l) + { + #pragma omp section + { + int v4m = v4j + v4k; + v4i = 8; + v4k = 10; + v4l++; + v4n = v4m + v4i; + } + #pragma omp section + { + int v4o = v4j + v4k; + v4i = 10; + v4k = 11; + v4l++; + } + } + return v4i + v4j + v4l + v4n; +} + +int +f5 (void) +{ + int v5i = 6, v5j = 7, v5k = 9, v5l = 0, v5n = 0, v5p = 0; + #pragma omp parallel + { + #pragma omp master + v5p++; + #pragma omp sections private (v5i) firstprivate (v5k) reduction (+:v5l) + { + #pragma omp section + { + int v5m = v5j + v5k; + v5i = 8; + v5k = 10; + v5l++; + v5n = v5m + v5i; + } + #pragma omp section + { + int v5o = v5j + v5k; + v5i = 10; + v5k = 11; + v5l++; + } + } + } + return v5i + v5j + v5l + v5n + v5p; +} + +int v6k = 9, v6l = 0; + +int +f6 (void) +{ + int v6i = 6, v6j = 7, v6n = 0; + #pragma omp for private (v6i) firstprivate (v6k) reduction (+:v6l) + for (v6n = 0; v6n < 3; v6n++) + { + int v6m = v6j + v6k; + v6i = 8; + v6l++; + } + return v6i + v6j + v6k + v6l + v6n; +} + +int +f7 (void) +{ + int v7i = 6, v7j = 7, v7k = 9, v7l = 0, v7n = 0, v7o = 1; + #pragma omp parallel + { + #pragma omp master + v7o++; + #pragma omp for private (v7i) firstprivate (v7k) reduction (+:v7l) + for (v7n = 0; v7n < 3; v7n++) + { + int v7m = v7j + v7k; + v7i = 8; + v7l++; + } + } + return v7i + v7j + v7k + v7l + v7n; +} + +int +main (void) +{ + f1 (); + f2 (); + f3 (); + f4 (); + f5 (); + f6 (); + f7 (); + return 0; +} |