This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Debug info support for OpenMP (PR debug/36617)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Diego Novillo <dnovillo at google dot com>, Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, gdb at gcc dot gnu dot org, Jan Kratochvil <jkratoch at redhat dot com>, Sami Wagiaalla <swagiaal at redhat dot com>
- Date: Fri, 27 Jun 2008 09:58:45 -0400
- Subject: [gomp] Debug info support for OpenMP (PR debug/36617)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Debug info was in theory supposed to work for OpenMP, we were keeping
VAR_DECLs with DECL_VALUE_EXPR e.g. for shared variables around, etc.
But in reality nothing was actually emitted. One of the problems
was that the DECL_INITIAL BLOCK of the destination ompfn didn't
have TREE_USED set, and setting it to 1 showed a lot of issues,
like all the variables were put into that one BLOCK, no subblocks
of the #pragma omp parallel/#pragma omp task were moved over to
the new function, worksharing constructs didn't care to preserve
BLOCKs, etc. Also, locus on many statements was incorrect.
The following patch fixes this, with -g -O0 -fopenmp on the attached
testcase I get useful debugging session (especially with OMP_NUM_THREADS=1
to avoid things in parallel), seeing the privatized and shared variables
that should be seen. For #pragma omp parallel (and task too) one steps
into the artificial *ompfn* function and isn't able to see there
the local variables of the original function that aren't ever mentioned
in the construct, except by doing up and looking at them in the parent
frame. If you have suggestions how to further improve this, please let
me know.
Diego, does this look ok?
2008-06-26 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.
* testsuite/libgomp.c/debug-1.c: New test.
--- gcc/tree-cfg.c.jj 2008-06-26 16:35:40.000000000 +0200
+++ gcc/tree-cfg.c 2008-06-26 19:49:17.000000000 +0200
@@ -5665,7 +5665,8 @@ replace_ssa_name (tree name, struct poin
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_subtree
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_b
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_
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
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
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);
--- gcc/tree-flow.h.jj 2008-06-26 16:35:40.000000000 +0200
+++ gcc/tree-flow.h 2008-06-26 16:45:36.000000000 +0200
@@ -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);
--- gcc/omp-low.c.jj 2008-06-26 16:35:56.000000000 +0200
+++ gcc/omp-low.c 2008-06-27 12:42:28.000000000 +0200
@@ -3140,7 +3140,7 @@ expand_omp_taskreg (struct omp_region *r
{
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 *r
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 *r
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_co
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_cont
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_fo
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
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
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_con
/* 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_con
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,
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. */
--- libgomp/testsuite/libgomp.c/debug-1.c.jj 2008-06-27 15:26:04.000000000 +0200
+++ libgomp/testsuite/libgomp.c/debug-1.c 2008-06-27 15:25:41.000000000 +0200
@@ -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;
+}
Jakub