OSDN Git Service

* java-tree.h (push_labeled_block, pop_labeled_block): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / omp-low.c
index e5a320d..feced73 100644 (file)
@@ -3,13 +3,13 @@
    marshalling to implement data sharing and copying clauses.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
-   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -18,9 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -41,6 +40,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "tree-pass.h"
 #include "ggc.h"
 #include "except.h"
+#include "splay-tree.h"
 
 
 /* Lowering of OpenMP parallel and workshare constructs proceeds in two 
@@ -384,9 +384,12 @@ determine_parallel_type (struct omp_region *region)
 
   if (single_succ (par_entry_bb) == ws_entry_bb
       && single_succ (ws_exit_bb) == par_exit_bb
-      && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb))
+      && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
+      && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
+         || (last_and_only_stmt (ws_entry_bb)
+             && last_and_only_stmt (par_exit_bb))))
     {
-      tree ws_stmt = last_stmt (region->inner->entry);
+      tree ws_stmt = last_stmt (ws_entry_bb);
 
       if (region->inner->type == OMP_FOR)
        {
@@ -441,17 +444,17 @@ is_reference (tree decl)
 static inline tree
 lookup_decl (tree var, omp_context *ctx)
 {
-  splay_tree_node n;
-  n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
-  return (tree) n->value;
+  tree *n;
+  n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
+  return *n;
 }
 
 static inline tree
 maybe_lookup_decl (tree var, omp_context *ctx)
 {
-  splay_tree_node n;
-  n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
-  return n ? (tree) n->value : NULL_TREE;
+  tree *n;
+  n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
+  return n ? *n : NULL_TREE;
 }
 
 static inline tree
@@ -515,6 +518,7 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
 
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
   DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+  DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
   TREE_USED (copy) = 1;
@@ -844,7 +848,7 @@ new_omp_context (tree stmt, omp_context *outer_ctx)
       ctx->depth = 1;
     }
 
-  ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+  ctx->cb.decl_map = pointer_map_create ();
 
   return ctx;
 }
@@ -857,7 +861,7 @@ delete_omp_context (splay_tree_value value)
 {
   omp_context *ctx = (omp_context *) value;
 
-  splay_tree_delete (ctx->cb.decl_map);
+  pointer_map_destroy (ctx->cb.decl_map);
 
   if (ctx->field_map)
     splay_tree_delete (ctx->field_map);
@@ -1427,10 +1431,7 @@ scan_omp (tree *stmt_p, omp_context *ctx)
 static void
 build_omp_barrier (tree *stmt_list)
 {
-  tree t;
-
-  t = built_in_decls[BUILT_IN_GOMP_BARRIER];
-  t = build_function_call_expr (t, NULL);
+  tree t = build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
   gimplify_and_add (t, stmt_list);
 }
 
@@ -1505,9 +1506,9 @@ lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
   for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
     t = maybe_lookup_decl (decl, up);
 
-  gcc_assert (t);
+  gcc_assert (t || is_global_var (decl));
 
-  return t;
+  return t ? t : decl;
 }
 
 
@@ -1604,7 +1605,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
                         omp_context *ctx)
 {
   tree_stmt_iterator diter;
-  tree c, dtor, copyin_seq, x, args, ptr;
+  tree c, dtor, copyin_seq, x, ptr;
   bool copyin_by_ref = false;
   bool lastprivate_firstprivate = false;
   int pass;
@@ -1676,11 +1677,9 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
              gcc_assert (DECL_P (ptr));
 
              x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
-             args = tree_cons (NULL, x, NULL);
-             x = built_in_decls[BUILT_IN_ALLOCA];
-             x = build_function_call_expr (x, args);
+             x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
              x = fold_convert (TREE_TYPE (ptr), x);
-             x = build2 (GIMPLE_MODIFY_STMT, void_type_node, ptr, x);
+             x = build_gimple_modify_stmt (ptr, x);
              gimplify_and_add (x, ilist);
            }
          else if (is_reference (var))
@@ -1710,13 +1709,11 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
                }
              else
                {
-                 args = tree_cons (NULL, x, NULL);
-                 x = built_in_decls[BUILT_IN_ALLOCA];
-                 x = build_function_call_expr (x, args);
+                 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
                  x = fold_convert (TREE_TYPE (new_var), x);
                }
 
-             x = build2 (GIMPLE_MODIFY_STMT, void_type_node, new_var, x);
+             x = build_gimple_modify_stmt (new_var, x);
              gimplify_and_add (x, ilist);
 
              new_var = build_fold_indirect_ref (new_var);
@@ -1799,7 +1796,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
                {
                  x = omp_reduction_init (c, TREE_TYPE (new_var));
                  gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
-                 x = build2 (GIMPLE_MODIFY_STMT, void_type_node, new_var, x);
+                 x = build_gimple_modify_stmt (new_var, x);
                  gimplify_and_add (x, ilist);
                }
              break;
@@ -1815,8 +1812,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
      but it certainly is to C++ operator=.  */
   if (copyin_seq)
     {
-      x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
-      x = build_function_call_expr (x, NULL);
+      x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
       x = build2 (NE_EXPR, boolean_type_node, x,
                  build_int_cst (TREE_TYPE (x), 0));
       x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
@@ -1964,19 +1960,17 @@ lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
        {
          x = build2 (code, TREE_TYPE (ref), ref, new_var);
          ref = build_outer_var_ref (var, ctx);
-         x = build2 (GIMPLE_MODIFY_STMT, void_type_node, ref, x);
+         x = build_gimple_modify_stmt (ref, x);
          append_to_statement_list (x, &sub_list);
        }
     }
 
-  x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
-  x = build_function_call_expr (x, NULL);
+  x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
   gimplify_and_add (x, stmt_list);
 
   gimplify_and_add (sub_list, stmt_list);
 
-  x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
-  x = build_function_call_expr (x, NULL);
+  x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
   gimplify_and_add (x, stmt_list);
 }
 
@@ -2003,7 +1997,7 @@ lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
       ref = build_sender_ref (var, ctx);
       x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
       x = by_ref ? build_fold_addr_expr (x) : x;
-      x = build2 (GIMPLE_MODIFY_STMT, void_type_node, ref, x);
+      x = build_gimple_modify_stmt (ref, x);
       gimplify_and_add (x, slist);
 
       ref = build_receiver_ref (var, by_ref, ctx);
@@ -2084,14 +2078,14 @@ lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
        {
          ref = build_sender_ref (val, ctx);
          x = by_ref ? build_fold_addr_expr (var) : var;
-         x = build2 (GIMPLE_MODIFY_STMT, void_type_node, ref, x);
+         x = build_gimple_modify_stmt (ref, x);
          gimplify_and_add (x, ilist);
        }
 
       if (do_out)
        {
          ref = build_sender_ref (val, ctx);
-         x = build2 (GIMPLE_MODIFY_STMT, void_type_node, var, ref);
+         x = build_gimple_modify_stmt (var, ref);
          gimplify_and_add (x, olist);
        }
     }
@@ -2128,17 +2122,17 @@ lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
        {
          x = build_sender_ref (ovar, ctx);
          var = build_fold_addr_expr (var);
-         x = build2 (GIMPLE_MODIFY_STMT, void_type_node, x, var);
+         x = build_gimple_modify_stmt (x, var);
          gimplify_and_add (x, ilist);
        }
       else
        {
          x = build_sender_ref (ovar, ctx);
-         x = build2 (GIMPLE_MODIFY_STMT, void_type_node, x, var);
+         x = build_gimple_modify_stmt (x, var);
          gimplify_and_add (x, ilist);
 
          x = build_sender_ref (ovar, ctx);
-         x = build2 (GIMPLE_MODIFY_STMT, void_type_node, var, x);
+         x = build_gimple_modify_stmt (var, x);
          gimplify_and_add (x, olist);
        }
     }
@@ -2155,7 +2149,7 @@ static void
 expand_parallel_call (struct omp_region *region, basic_block bb,
                      tree entry_stmt, tree ws_args)
 {
-  tree t, args, val, cond, c, list, clauses;
+  tree t, t1, t2, val, cond, c, list, clauses;
   block_stmt_iterator si;
   int start_ix;
 
@@ -2212,7 +2206,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
        {
          basic_block cond_bb, then_bb, else_bb;
          edge e;
-         tree t, then_lab, else_lab, tmp;
+         tree t, tmp;
 
          tmp = create_tmp_var (TREE_TYPE (val), NULL);
          e = split_block (bb, NULL);
@@ -2222,28 +2216,20 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
 
          then_bb = create_empty_bb (cond_bb);
          else_bb = create_empty_bb (then_bb);
-         then_lab = create_artificial_label ();
-         else_lab = create_artificial_label ();
 
          t = build3 (COND_EXPR, void_type_node,
-                     cond,
-                     build_and_jump (&then_lab),
-                     build_and_jump (&else_lab));
+                     cond, NULL_TREE, NULL_TREE);
 
          si = bsi_start (cond_bb);
          bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
 
          si = bsi_start (then_bb);
-         t = build1 (LABEL_EXPR, void_type_node, then_lab);
-         bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
-         t = build2 (GIMPLE_MODIFY_STMT, void_type_node, tmp, val);
+         t = build_gimple_modify_stmt (tmp, val);
          bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
 
          si = bsi_start (else_bb);
-         t = build1 (LABEL_EXPR, void_type_node, else_lab);
-         bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
-         t = build2 (GIMPLE_MODIFY_STMT, void_type_node, tmp, 
-                     build_int_cst (unsigned_type_node, 1));
+         t = build_gimple_modify_stmt (tmp, 
+                                       build_int_cst (unsigned_type_node, 1));
          bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
 
          make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
@@ -2261,21 +2247,23 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
     }
 
   list = NULL_TREE;
-  args = tree_cons (NULL, val, NULL);
   t = OMP_PARALLEL_DATA_ARG (entry_stmt);
   if (t == NULL)
-    t = null_pointer_node;
+    t1 = null_pointer_node;
   else
-    t = build_fold_addr_expr (t);
-  args = tree_cons (NULL, t, args);
-  t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
-  args = tree_cons (NULL, t, args);
+    t1 = build_fold_addr_expr (t);
+  t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
 
   if (ws_args)
-    args = chainon (args, ws_args);
+    {
+      tree args = tree_cons (NULL, t2,
+                            tree_cons (NULL, t1,
+                                       tree_cons (NULL, val, ws_args)));
+      t = build_function_call_expr (built_in_decls[start_ix], args);
+    }
+  else
+    t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
 
-  t = built_in_decls[start_ix];
-  t = build_function_call_expr (t, args);
   gimplify_and_add (t, &list);
 
   t = OMP_PARALLEL_DATA_ARG (entry_stmt);
@@ -2283,12 +2271,10 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
     t = null_pointer_node;
   else
     t = build_fold_addr_expr (t);
-  args = tree_cons (NULL, t, NULL);
-  t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
+  t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
   gimplify_and_add (t, &list);
 
-  t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
   gimplify_and_add (t, &list);
 
   si = bsi_last (bb);
@@ -2313,10 +2299,7 @@ maybe_catch_exception (tree *stmt_p)
   if (lang_protect_cleanup_actions)
     t = lang_protect_cleanup_actions ();
   else
-    {
-      t = built_in_decls[BUILT_IN_TRAP];
-      t = build_function_call_expr (t, NULL);
-    }
+    t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
   f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
   EH_FILTER_MUST_NOT_THROW (f) = 1;
   gimplify_and_add (t, &EH_FILTER_FAILURE (f));
@@ -2421,6 +2404,7 @@ expand_omp_parallel (struct omp_region *region)
   block_stmt_iterator si;
   tree entry_stmt;
   edge e;
+  bool do_cleanup_cfg = false;
 
   entry_stmt = last_stmt (region->entry);
   child_fn = OMP_PARALLEL_FN (entry_stmt);
@@ -2456,6 +2440,7 @@ expand_omp_parallel (struct omp_region *region)
          exit_succ_e = single_succ_edge (exit_bb);
          make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
        }
+      do_cleanup_cfg = true;
     }
   else
     {
@@ -2505,7 +2490,7 @@ expand_omp_parallel (struct omp_region *region)
       /* Declare local variables needed in CHILD_CFUN.  */
       block = DECL_INITIAL (child_fn);
       BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
-      DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
+      DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
 
       /* Reset DECL_CONTEXT on locals and function arguments.  */
       for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
@@ -2549,6 +2534,14 @@ expand_omp_parallel (struct omp_region *region)
 
   /* Emit a library call to launch the children threads.  */
   expand_parallel_call (region, new_bb, entry_stmt, ws_args);
+
+  if (do_cleanup_cfg)
+    {
+      /* Clean up the unreachable sub-graph we created above.  */
+      free_dominance_info (CDI_DOMINATORS);
+      free_dominance_info (CDI_POST_DOMINATORS);
+      cleanup_tree_cfg ();
+    }
 }
 
 
@@ -2581,9 +2574,8 @@ expand_omp_for_generic (struct omp_region *region,
                        enum built_in_function start_fn,
                        enum built_in_function next_fn)
 {
-  tree l0, l1, l2 = NULL, l3 = NULL;
   tree type, istart0, iend0, iend;
-  tree t, args, list;
+  tree t, list;
   basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
   basic_block l2_bb = NULL, l3_bb = NULL;
   block_stmt_iterator si;
@@ -2603,48 +2595,40 @@ expand_omp_for_generic (struct omp_region *region,
   l0_bb = create_empty_bb (entry_bb);
   l1_bb = single_succ (entry_bb);
 
-  l0 = tree_block_label (l0_bb);
-  l1 = tree_block_label (l1_bb);
-
   cont_bb = region->cont;
   exit_bb = region->exit;
   if (cont_bb)
     {
       l2_bb = create_empty_bb (cont_bb);
       l3_bb = single_succ (cont_bb);
-
-      l2 = tree_block_label (l2_bb);
-      l3 = tree_block_label (l3_bb);
     }
 
   si = bsi_last (entry_bb);
   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
   if (!in_combined_parallel)
     {
+      tree t0, t1, t2, t3, t4;
       /* If this is not a combined parallel loop, emit a call to
         GOMP_loop_foo_start in ENTRY_BB.  */
       list = alloc_stmt_list ();
-      t = build_fold_addr_expr (iend0);
-      args = tree_cons (NULL, t, NULL);
-      t = build_fold_addr_expr (istart0);
-      args = tree_cons (NULL, t, args);
+      t4 = build_fold_addr_expr (iend0);
+      t3 = build_fold_addr_expr (istart0);
+      t2 = fold_convert (long_integer_type_node, fd->step);
+      t1 = fold_convert (long_integer_type_node, fd->n2);
+      t0 = fold_convert (long_integer_type_node, fd->n1);
       if (fd->chunk_size)
        {
          t = fold_convert (long_integer_type_node, fd->chunk_size);
-         args = tree_cons (NULL, t, args);
+         t = build_call_expr (built_in_decls[start_fn], 6,
+                              t0, t1, t2, t, t3, t4);
        }
-      t = fold_convert (long_integer_type_node, fd->step);
-      args = tree_cons (NULL, t, args);
-      t = fold_convert (long_integer_type_node, fd->n2);
-      args = tree_cons (NULL, t, args);
-      t = fold_convert (long_integer_type_node, fd->n1);
-      args = tree_cons (NULL, t, args);
-      t = build_function_call_expr (built_in_decls[start_fn], args);
+      else
+       t = build_call_expr (built_in_decls[start_fn], 5,
+                            t0, t1, t2, t3, t4);
       t = get_formal_tmp_var (t, &list);
       if (cont_bb)
        {
-         t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
-                     build_and_jump (&l3));
+         t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
          append_to_statement_list (t, &list);
        }
       bsi_insert_after (&si, list, BSI_SAME_STMT);
@@ -2654,11 +2638,11 @@ expand_omp_for_generic (struct omp_region *region,
   /* Iteration setup for sequential loop goes in L0_BB.  */
   list = alloc_stmt_list ();
   t = fold_convert (type, istart0);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, t);
+  t = build_gimple_modify_stmt (fd->v, t);
   gimplify_and_add (t, &list);
 
   t = fold_convert (type, iend0);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, iend, t);
+  t = build_gimple_modify_stmt (iend, t);
   gimplify_and_add (t, &list);
 
   si = bsi_start (l0_bb);
@@ -2680,13 +2664,12 @@ expand_omp_for_generic (struct omp_region *region,
   list = alloc_stmt_list ();
 
   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, t);
+  t = build_gimple_modify_stmt (fd->v, t);
   gimplify_and_add (t, &list);
   
   t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
   t = get_formal_tmp_var (t, &list);
-  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
-             build_and_jump (&l2));
+  t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
   append_to_statement_list (t, &list);
 
   si = bsi_last (cont_bb);
@@ -2697,14 +2680,11 @@ expand_omp_for_generic (struct omp_region *region,
   /* Emit code to get the next parallel iteration in L2_BB.  */
   list = alloc_stmt_list ();
 
-  t = build_fold_addr_expr (iend0);
-  args = tree_cons (NULL, t, NULL);
-  t = build_fold_addr_expr (istart0);
-  args = tree_cons (NULL, t, args);
-  t = build_function_call_expr (built_in_decls[next_fn], args);
+  t = build_call_expr (built_in_decls[next_fn], 2,
+                      build_fold_addr_expr (istart0),
+                      build_fold_addr_expr (iend0));
   t = get_formal_tmp_var (t, &list);
-  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
-             build_and_jump (&l3));
+  t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
   append_to_statement_list (t, &list);
   
   si = bsi_start (l2_bb);
@@ -2716,7 +2696,7 @@ expand_omp_for_generic (struct omp_region *region,
     t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
   else
     t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (t, 0);
   bsi_insert_after (&si, t, BSI_SAME_STMT);
   bsi_remove (&si, true);
 
@@ -2773,7 +2753,7 @@ static void
 expand_omp_for_static_nochunk (struct omp_region *region,
                               struct omp_for_data *fd)
 {
-  tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
+  tree n, q, s0, e0, e, t, nthreads, threadid;
   tree type, list;
   basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
   basic_block fin_bb;
@@ -2788,20 +2768,14 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   fin_bb = single_succ (cont_bb);
   exit_bb = region->exit;
 
-  l0 = tree_block_label (seq_start_bb);
-  l1 = tree_block_label (body_bb);
-  l2 = tree_block_label (fin_bb);
-
   /* Iteration space partitioning goes in ENTRY_BB.  */
   list = alloc_stmt_list ();
 
-  t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
   t = fold_convert (type, t);
   nthreads = get_formal_tmp_var (t, &list);
   
-  t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
   t = fold_convert (type, t);
   threadid = get_formal_tmp_var (t, &list);
 
@@ -2844,8 +2818,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   e0 = get_formal_tmp_var (t, &list);
 
   t = build2 (GE_EXPR, boolean_type_node, s0, e0);
-  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
-             build_and_jump (&l0));
+  t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
   append_to_statement_list (t, &list);
 
   si = bsi_last (entry_bb);
@@ -2859,7 +2832,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   t = fold_convert (type, s0);
   t = build2 (MULT_EXPR, type, t, fd->step);
   t = build2 (PLUS_EXPR, type, t, fd->n1);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, t);
+  t = build_gimple_modify_stmt (fd->v, t);
   gimplify_and_add (t, &list);
 
   t = fold_convert (type, e0);
@@ -2874,13 +2847,12 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   list = alloc_stmt_list ();
 
   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, t);
+  t = build_gimple_modify_stmt (fd->v, t);
   gimplify_and_add (t, &list);
 
   t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
   t = get_formal_tmp_var (t, &list);
-  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
-             build_and_jump (&l2));
+  t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
   append_to_statement_list (t, &list);
 
   si = bsi_last (cont_bb);
@@ -2944,7 +2916,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
 static void
 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
 {
-  tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
+  tree n, s0, e0, e, t;
   tree trip, nthreads, threadid;
   tree type;
   basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
@@ -2963,22 +2935,14 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   fin_bb = single_succ (cont_bb);
   exit_bb = region->exit;
 
-  l0 = tree_block_label (iter_part_bb);
-  l1 = tree_block_label (seq_start_bb);
-  l2 = tree_block_label (body_bb);
-  l3 = tree_block_label (trip_update_bb);
-  l4 = tree_block_label (fin_bb);
-
   /* Trip and adjustment setup goes in ENTRY_BB.  */
   list = alloc_stmt_list ();
 
-  t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
   t = fold_convert (type, t);
   nthreads = get_formal_tmp_var (t, &list);
   
-  t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
   t = fold_convert (type, t);
   threadid = get_formal_tmp_var (t, &list);
 
@@ -3030,8 +2994,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   e0 = get_formal_tmp_var (t, &list);
 
   t = build2 (LT_EXPR, boolean_type_node, s0, n);
-  t = build3 (COND_EXPR, void_type_node, t,
-             build_and_jump (&l1), build_and_jump (&l4));
+  t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
   append_to_statement_list (t, &list);
 
   si = bsi_start (iter_part_bb);
@@ -3043,7 +3006,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   t = fold_convert (type, s0);
   t = build2 (MULT_EXPR, type, t, fd->step);
   t = build2 (PLUS_EXPR, type, t, fd->n1);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, t);
+  t = build_gimple_modify_stmt (fd->v, t);
   gimplify_and_add (t, &list);
 
   t = fold_convert (type, e0);
@@ -3059,13 +3022,12 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   list = alloc_stmt_list ();
 
   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, t);
+  t = build_gimple_modify_stmt (fd->v, t);
   gimplify_and_add (t, &list);
 
   t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
   t = get_formal_tmp_var (t, &list);
-  t = build3 (COND_EXPR, void_type_node, t,
-             build_and_jump (&l2), build_and_jump (&l3));
+  t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
   append_to_statement_list (t, &list);
   
   si = bsi_last (cont_bb);
@@ -3078,7 +3040,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
 
   t = build_int_cst (type, 1);
   t = build2 (PLUS_EXPR, type, trip, t);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, trip, t);
+  t = build_gimple_modify_stmt (trip, t);
   gimplify_and_add (t, &list);
 
   si = bsi_start (trip_update_bb);
@@ -3224,10 +3186,9 @@ expand_omp_sections (struct omp_region *region)
       /* If we are not inside a combined parallel+sections region,
         call GOMP_sections_start.  */
       t = build_int_cst (unsigned_type_node, len);
-      t = tree_cons (NULL, t, NULL);
       u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
-      t = build_function_call_expr (u, t);
-      t = build2 (GIMPLE_MODIFY_STMT, void_type_node, v, t);
+      t = build_call_expr (u, 1, t);
+      t = build_gimple_modify_stmt (v, t);
       bsi_insert_after (&si, t, BSI_SAME_STMT);
     }
   bsi_remove (&si, true);
@@ -3284,8 +3245,7 @@ expand_omp_sections (struct omp_region *region)
   make_edge (l0_bb, default_bb, 0);
 
   si = bsi_start (default_bb);
-  t = built_in_decls[BUILT_IN_TRAP];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
 
   /* Code to get the next section goes in L1_BB.  */
@@ -3294,9 +3254,8 @@ expand_omp_sections (struct omp_region *region)
       si = bsi_last (l1_bb);
       gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
 
-      t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
-      t = build_function_call_expr (t, NULL);
-      t = build2 (GIMPLE_MODIFY_STMT, void_type_node, v, t);
+      t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
+      t = build_gimple_modify_stmt (v, t);
       bsi_insert_after (&si, t, BSI_SAME_STMT);
       bsi_remove (&si, true);
     }
@@ -3309,7 +3268,7 @@ expand_omp_sections (struct omp_region *region)
        t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
       else
        t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
-      t = build_function_call_expr (t, NULL);
+      t = build_call_expr (t, 0);
       bsi_insert_after (&si, t, BSI_SAME_STMT);
       bsi_remove (&si, true);
     }
@@ -3680,8 +3639,7 @@ lower_omp_single_simple (tree single_stmt, tree *pre_p)
 {
   tree t;
 
-  t = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
   t = build3 (COND_EXPR, void_type_node, t,
              OMP_SINGLE_BODY (single_stmt), NULL);
   gimplify_and_add (t, pre_p);
@@ -3720,7 +3678,7 @@ lower_omp_single_simple (tree single_stmt, tree *pre_p)
 static void
 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
 {
-  tree ptr_type, t, args, l0, l1, l2, copyin_seq;
+  tree ptr_type, t, l0, l1, l2, copyin_seq;
 
   ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
 
@@ -3731,10 +3689,9 @@ lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
   l1 = create_artificial_label ();
   l2 = create_artificial_label ();
 
-  t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START];
-  t = build_function_call_expr (t, NULL);
+  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
   t = fold_convert (ptr_type, t);
-  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, ctx->receiver_decl, t);
+  t = build_gimple_modify_stmt (ctx->receiver_decl, t);
   gimplify_and_add (t, pre_p);
 
   t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
@@ -3753,9 +3710,7 @@ lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
                              &copyin_seq, ctx);
 
   t = build_fold_addr_expr (ctx->sender_decl);
-  args = tree_cons (NULL, t, NULL);
-  t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END];
-  t = build_function_call_expr (t, args);
+  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
   gimplify_and_add (t, pre_p);
 
   t = build_and_jump (&l2);
@@ -3828,8 +3783,7 @@ lower_omp_master (tree *stmt_p, omp_context *ctx)
 
   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
 
-  x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
-  x = build_function_call_expr (x, NULL);
+  x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
   x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
   x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
@@ -3868,8 +3822,7 @@ lower_omp_ordered (tree *stmt_p, omp_context *ctx)
 
   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
 
-  x = built_in_decls[BUILT_IN_GOMP_ORDERED_START];
-  x = build_function_call_expr (x, NULL);
+  x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
 
   lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
@@ -3877,8 +3830,7 @@ lower_omp_ordered (tree *stmt_p, omp_context *ctx)
   append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
   OMP_ORDERED_BODY (stmt) = NULL;
 
-  x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
-  x = build_function_call_expr (x, NULL);
+  x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
 
   x = make_node (OMP_RETURN);
@@ -3909,7 +3861,7 @@ lower_omp_critical (tree *stmt_p, omp_context *ctx)
   name = OMP_CRITICAL_NAME (stmt);
   if (name)
     {
-      tree decl, args;
+      tree decl;
       splay_tree_node n;
 
       if (!critical_name_mutexes)
@@ -3939,21 +3891,19 @@ lower_omp_critical (tree *stmt_p, omp_context *ctx)
       else
        decl = (tree) n->value;
 
-      args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
       lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
-      lock = build_function_call_expr (lock, args);
+      lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
 
-      args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
       unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
-      unlock = build_function_call_expr (unlock, args);
+      unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
     }
   else
     {
       lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
-      lock = build_function_call_expr (lock, NULL);
+      lock = build_call_expr (lock, 0);
 
       unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
-      unlock = build_function_call_expr (unlock, NULL);
+      unlock = build_call_expr (unlock, 0);
     }
 
   push_gimplify_context ();
@@ -4026,7 +3976,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
 
       /* Initialize the iterator variable, so that threads that don't execute
         any iterations don't execute the lastprivate clauses by accident.  */
-      t = build2 (GIMPLE_MODIFY_STMT, void_type_node, fd->v, vinit);
+      t = build_gimple_modify_stmt (fd->v, vinit);
       gimplify_and_add (t, body_p);
     }
 }
@@ -4112,6 +4062,28 @@ lower_omp_for (tree *stmt_p, omp_context *ctx)
   *stmt_p = new_stmt;
 }
 
+/* Callback for walk_stmts.  Check if *TP only contains OMP_FOR
+   or OMP_PARALLEL.  */
+
+static tree
+check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
+{
+  struct walk_stmt_info *wi = data;
+  int *info = wi->info;
+
+  *walk_subtrees = 0;
+  switch (TREE_CODE (*tp))
+    {
+    case OMP_FOR:
+    case OMP_SECTIONS:
+      *info = *info == 0 ? 1 : -1;
+      break;
+    default:
+      *info = -1;
+      break;
+    }
+  return NULL;
+}
 
 /* Lower the OpenMP parallel directive in *STMT_P.  CTX holds context
    information for the directive.  */
@@ -4129,6 +4101,19 @@ lower_omp_parallel (tree *stmt_p, omp_context *ctx)
   par_bind = OMP_PARALLEL_BODY (stmt);
   par_body = BIND_EXPR_BODY (par_bind);
   child_fn = ctx->cb.dst_fn;
+  if (!OMP_PARALLEL_COMBINED (stmt))
+    {
+      struct walk_stmt_info wi;
+      int ws_num = 0;
+
+      memset (&wi, 0, sizeof (wi));
+      wi.callback = check_combined_parallel;
+      wi.info = &ws_num;
+      wi.val_only = true;
+      walk_stmts (&wi, &par_bind);
+      if (ws_num == 1)
+       OMP_PARALLEL_COMBINED (stmt) = 1;
+    }
 
   push_gimplify_context ();
 
@@ -4166,7 +4151,7 @@ lower_omp_parallel (tree *stmt_p, omp_context *ctx)
       t = build_fold_addr_expr (ctx->sender_decl);
       /* fixup_child_record_type might have changed receiver_decl's type.  */
       t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
-      t = build2 (GIMPLE_MODIFY_STMT, void_type_node, ctx->receiver_decl, t);
+      t = build_gimple_modify_stmt (ctx->receiver_decl, t);
       append_to_statement_list (t, &new_body);
     }
 
@@ -4218,7 +4203,7 @@ init_tmp_var (tree exp, tree_stmt_iterator *tsi)
 
   t = create_tmp_var (TREE_TYPE (exp), NULL);
   DECL_GIMPLE_REG_P (t) = 1;
-  stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (t), t, exp);
+  stmt = build_gimple_modify_stmt (t, exp);
   SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
   tsi_link_before (tsi, stmt, TSI_SAME_STMT);
 
@@ -4235,7 +4220,7 @@ save_tmp_var (tree exp, tree_stmt_iterator *tsi)
 
   t = create_tmp_var (TREE_TYPE (exp), NULL);
   DECL_GIMPLE_REG_P (t) = 1;
-  stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (t), exp, t);
+  stmt = build_gimple_modify_stmt (exp, t);
   SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
   tsi_link_after (tsi, stmt, TSI_SAME_STMT);