re PR debug/36617 (Debug info for OpenMP code is almost non-existent)
authorJakub Jelinek <jakub@redhat.com>
Fri, 27 Jun 2008 19:42:32 +0000 (21:42 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 27 Jun 2008 19:42:32 +0000 (21:42 +0200)
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

gcc/ChangeLog
gcc/omp-low.c
gcc/tree-cfg.c
gcc/tree-flow.h
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/debug-1.c [new file with mode: 0644]

index f1279f8b7af05d833538187ef57e8191d2796209..38ce1cff59452b3265e2c271ab3d96503528f334 100644 (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
index e26ebbcb9d70bcb43d1955ffd5e502ad1dfe63e5..e5680077bd0a4c9dda6acdba6f048c2f3908832f 100644 (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;
 }
 \f
 /* Main entry point.  */
index 50f53a080e83ffa4846c3ca1bc1268c22646c3d1..341a1de749d91ff23afd41e2adf8fc28c149506a 100644 (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);
index 15329ac002ec9400ddb2b0e76eb2aa5d18146431..ded7687b75ebf7a572b7e97e0521fc0551d41879 100644 (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);
 
index ed27454354eab84596b9456dc6af99a330a4bf70..18e1bf7c43a055bf1c7818c438e475414d782e77 100644 (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.
diff --git a/libgomp/testsuite/libgomp.c/debug-1.c b/libgomp/testsuite/libgomp.c/debug-1.c
new file mode 100644 (file)
index 0000000..09bcf7f
--- /dev/null
@@ -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;
+}