re PR debug/36617 (Debug info for OpenMP code is almost non-existent)

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.

	* testsuite/libgomp.c/debug-1.c: New test.

From-SVN: r137198
This commit is contained in:
Jakub Jelinek 2008-06-27 21:42:32 +02:00 committed by Jakub Jelinek
parent b7091901cd
commit b357f682db
6 changed files with 349 additions and 47 deletions

View File

@ -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

View File

@ -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. */

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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;
}