OSDN Git Service

Update gcc.dg/atomic-flag.c test for non-boolean TAS targets.
[pf3gnuchains/gcc-fork.git] / gcc / omp-low.c
index e8b2b4d..8ab689d 100644 (file)
@@ -3,7 +3,8 @@
    marshalling to implement data sharing and copying clauses.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
    marshalling to implement data sharing and copying clauses.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
-   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -31,13 +32,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-iterator.h"
 #include "tree-inline.h"
 #include "langhooks.h"
 #include "tree-iterator.h"
 #include "tree-inline.h"
 #include "langhooks.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
 #include "tree-flow.h"
 #include "timevar.h"
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
 #include "tree-flow.h"
 #include "timevar.h"
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
-#include "toplev.h"
 #include "tree-pass.h"
 #include "ggc.h"
 #include "except.h"
 #include "tree-pass.h"
 #include "ggc.h"
 #include "except.h"
@@ -46,7 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 
 
 #include "cfgloop.h"
 
 
-/* Lowering of OpenMP parallel and workshare constructs proceeds in two 
+/* Lowering of OpenMP parallel and workshare constructs proceeds in two
    phases.  The first phase scans the function looking for OMP statements
    and then for variables that must be replaced to satisfy data sharing
    clauses.  The second phase expands code for the constructs, as well as
    phases.  The first phase scans the function looking for OMP statements
    and then for variables that must be replaced to satisfy data sharing
    clauses.  The second phase expands code for the constructs, as well as
@@ -72,7 +72,7 @@ typedef struct omp_context
   struct omp_context *outer;
   gimple stmt;
 
   struct omp_context *outer;
   gimple stmt;
 
-  /* Map variables to fields in a structure that allows communication 
+  /* Map variables to fields in a structure that allows communication
      between sending and receiving threads.  */
   splay_tree field_map;
   tree record_type;
      between sending and receiving threads.  */
   splay_tree field_map;
   tree record_type;
@@ -139,6 +139,7 @@ static tree scan_omp_1_op (tree *, int *, void *);
     case GIMPLE_TRY: \
     case GIMPLE_CATCH: \
     case GIMPLE_EH_FILTER: \
     case GIMPLE_TRY: \
     case GIMPLE_CATCH: \
     case GIMPLE_EH_FILTER: \
+    case GIMPLE_TRANSACTION: \
       /* The sub-statements for these should be walked.  */ \
       *handled_ops_p = false; \
       break;
       /* The sub-statements for these should be walked.  */ \
       *handled_ops_p = false; \
       break;
@@ -222,6 +223,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
   struct omp_for_data_loop *loop;
   int i;
   struct omp_for_data_loop dummy_loop;
   struct omp_for_data_loop *loop;
   int i;
   struct omp_for_data_loop dummy_loop;
+  location_t loc = gimple_location (for_stmt);
 
   fd->for_stmt = for_stmt;
   fd->pre = NULL;
 
   fd->for_stmt = for_stmt;
   fd->pre = NULL;
@@ -292,7 +294,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
       else
        loop = &dummy_loop;
 
       else
        loop = &dummy_loop;
 
-      
+
       loop->v = gimple_omp_for_index (for_stmt, i);
       gcc_assert (SSA_VAR_P (loop->v));
       gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
       loop->v = gimple_omp_for_index (for_stmt, i);
       gcc_assert (SSA_VAR_P (loop->v));
       gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
@@ -309,19 +311,19 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
          break;
        case LE_EXPR:
          if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
          break;
        case LE_EXPR:
          if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
-           loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
-                                   loop->n2, size_one_node);
+           loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
          else
          else
-           loop->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
+           loop->n2 = fold_build2_loc (loc,
+                                   PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
                                    build_int_cst (TREE_TYPE (loop->n2), 1));
          loop->cond_code = LT_EXPR;
          break;
        case GE_EXPR:
          if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
                                    build_int_cst (TREE_TYPE (loop->n2), 1));
          loop->cond_code = LT_EXPR;
          break;
        case GE_EXPR:
          if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
-           loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
-                                   loop->n2, size_int (-1));
+           loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
          else
          else
-           loop->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
+           loop->n2 = fold_build2_loc (loc,
+                                   MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
                                    build_int_cst (TREE_TYPE (loop->n2), 1));
          loop->cond_code = GT_EXPR;
          break;
                                    build_int_cst (TREE_TYPE (loop->n2), 1));
          loop->cond_code = GT_EXPR;
          break;
@@ -339,7 +341,8 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
          break;
        case MINUS_EXPR:
          loop->step = TREE_OPERAND (t, 1);
          break;
        case MINUS_EXPR:
          loop->step = TREE_OPERAND (t, 1);
-         loop->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (loop->step),
+         loop->step = fold_build1_loc (loc,
+                                   NEGATE_EXPR, TREE_TYPE (loop->step),
                                    loop->step);
          break;
        default:
                                    loop->step);
          break;
        default:
@@ -357,7 +360,8 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
              tree n;
 
              if (loop->cond_code == LT_EXPR)
              tree n;
 
              if (loop->cond_code == LT_EXPR)
-               n = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
+               n = fold_build2_loc (loc,
+                                PLUS_EXPR, TREE_TYPE (loop->v),
                                 loop->n2, loop->step);
              else
                n = loop->n1;
                                 loop->n2, loop->step);
              else
                n = loop->n1;
@@ -373,12 +377,14 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
              if (loop->cond_code == LT_EXPR)
                {
                  n1 = loop->n1;
              if (loop->cond_code == LT_EXPR)
                {
                  n1 = loop->n1;
-                 n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
+                 n2 = fold_build2_loc (loc,
+                                   PLUS_EXPR, TREE_TYPE (loop->v),
                                    loop->n2, loop->step);
                }
              else
                {
                                    loop->n2, loop->step);
                }
              else
                {
-                 n1 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->v),
+                 n1 = fold_build2_loc (loc,
+                                   MINUS_EXPR, TREE_TYPE (loop->v),
                                    loop->n2, loop->step);
                  n2 = loop->n1;
                }
                                    loop->n2, loop->step);
                  n2 = loop->n1;
                }
@@ -404,24 +410,26 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
                itype
                  = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
              t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
                itype
                  = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
              t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
-             t = fold_build2 (PLUS_EXPR, itype,
-                              fold_convert (itype, loop->step), t);
-             t = fold_build2 (PLUS_EXPR, itype, t,
-                              fold_convert (itype, loop->n2));
-             t = fold_build2 (MINUS_EXPR, itype, t,
-                              fold_convert (itype, loop->n1));
+             t = fold_build2_loc (loc,
+                              PLUS_EXPR, itype,
+                              fold_convert_loc (loc, itype, loop->step), t);
+             t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
+                              fold_convert_loc (loc, itype, loop->n2));
+             t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
+                              fold_convert_loc (loc, itype, loop->n1));
              if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
              if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
-               t = fold_build2 (TRUNC_DIV_EXPR, itype,
-                                fold_build1 (NEGATE_EXPR, itype, t),
-                                fold_build1 (NEGATE_EXPR, itype,
-                                             fold_convert (itype,
-                                                           loop->step)));
+               t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
+                                fold_build1_loc (loc, NEGATE_EXPR, itype, t),
+                                fold_build1_loc (loc, NEGATE_EXPR, itype,
+                                             fold_convert_loc (loc, itype,
+                                                               loop->step)));
              else
              else
-               t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
-                                fold_convert (itype, loop->step));
-             t = fold_convert (long_long_unsigned_type_node, t);
+               t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
+                                fold_convert_loc (loc, itype, loop->step));
+             t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
              if (count != NULL_TREE)
              if (count != NULL_TREE)
-               count = fold_build2 (MULT_EXPR, long_long_unsigned_type_node,
+               count = fold_build2_loc (loc,
+                                    MULT_EXPR, long_long_unsigned_type_node,
                                     count, t);
              else
                count = t;
                                     count, t);
              else
                count = t;
@@ -448,7 +456,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
   if (collapse_count && *collapse_count == NULL)
     {
       if (count)
   if (collapse_count && *collapse_count == NULL)
     {
       if (count)
-       *collapse_count = fold_convert (iter_type, count);
+       *collapse_count = fold_convert_loc (loc, iter_type, count);
       else
        *collapse_count = create_tmp_var (iter_type, ".count");
     }
       else
        *collapse_count = create_tmp_var (iter_type, ".count");
     }
@@ -483,7 +491,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
        # BLOCK 2 (PAR_ENTRY_BB)
        .omp_data_o.i = i;
        #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
        # BLOCK 2 (PAR_ENTRY_BB)
        .omp_data_o.i = i;
        #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
-       
+
        # BLOCK 3 (WS_ENTRY_BB)
        .omp_data_i = &.omp_data_o;
        D.1667 = .omp_data_i->i;
        # BLOCK 3 (WS_ENTRY_BB)
        .omp_data_i = &.omp_data_o;
        D.1667 = .omp_data_i->i;
@@ -507,13 +515,10 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
    hack something up here, it is really not worth the aggravation.  */
 
 static bool
    hack something up here, it is really not worth the aggravation.  */
 
 static bool
-workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
+workshare_safe_to_combine_p (basic_block ws_entry_bb)
 {
   struct omp_for_data fd;
 {
   struct omp_for_data fd;
-  gimple par_stmt, ws_stmt;
-
-  par_stmt = last_stmt (par_entry_bb);
-  ws_stmt = last_stmt (ws_entry_bb);
+  gimple ws_stmt = last_stmt (ws_entry_bb);
 
   if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
     return true;
 
   if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
     return true;
@@ -546,33 +551,35 @@ workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
    parallel+workshare call.  WS_STMT is the workshare directive being
    expanded.  */
 
    parallel+workshare call.  WS_STMT is the workshare directive being
    expanded.  */
 
-static tree
+static VEC(tree,gc) *
 get_ws_args_for (gimple ws_stmt)
 {
   tree t;
 get_ws_args_for (gimple ws_stmt)
 {
   tree t;
+  location_t loc = gimple_location (ws_stmt);
+  VEC(tree,gc) *ws_args;
 
   if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
     {
       struct omp_for_data fd;
 
   if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
     {
       struct omp_for_data fd;
-      tree ws_args;
 
       extract_omp_for_data (ws_stmt, &fd, NULL);
 
 
       extract_omp_for_data (ws_stmt, &fd, NULL);
 
-      ws_args = NULL_TREE;
-      if (fd.chunk_size)
-       {
-         t = fold_convert (long_integer_type_node, fd.chunk_size);
-         ws_args = tree_cons (NULL, t, ws_args);
-       }
+      ws_args = VEC_alloc (tree, gc, 3 + (fd.chunk_size != 0));
+
+      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
+      VEC_quick_push (tree, ws_args, t);
 
 
-      t = fold_convert (long_integer_type_node, fd.loop.step);
-      ws_args = tree_cons (NULL, t, ws_args);
+      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
+      VEC_quick_push (tree, ws_args, t);
 
 
-      t = fold_convert (long_integer_type_node, fd.loop.n2);
-      ws_args = tree_cons (NULL, t, ws_args);
+      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
+      VEC_quick_push (tree, ws_args, t);
 
 
-      t = fold_convert (long_integer_type_node, fd.loop.n1);
-      ws_args = tree_cons (NULL, t, ws_args);
+      if (fd.chunk_size)
+       {
+         t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
+         VEC_quick_push (tree, ws_args, t);
+       }
 
       return ws_args;
     }
 
       return ws_args;
     }
@@ -583,8 +590,9 @@ get_ws_args_for (gimple ws_stmt)
         the exit of the sections region.  */
       basic_block bb = single_succ (gimple_bb (ws_stmt));
       t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
         the exit of the sections region.  */
       basic_block bb = single_succ (gimple_bb (ws_stmt));
       t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
-      t = tree_cons (NULL, t, NULL);
-      return t;
+      ws_args = VEC_alloc (tree, gc, 1);
+      VEC_quick_push (tree, ws_args, t);
+      return ws_args;
     }
 
   gcc_unreachable ();
     }
 
   gcc_unreachable ();
@@ -619,7 +627,7 @@ determine_parallel_type (struct omp_region *region)
 
   if (single_succ (par_entry_bb) == ws_entry_bb
       && single_succ (ws_exit_bb) == par_exit_bb
 
   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 (ws_entry_bb)
       && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
          || (last_and_only_stmt (ws_entry_bb)
              && last_and_only_stmt (par_exit_bb))))
       && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
          || (last_and_only_stmt (ws_entry_bb)
              && last_and_only_stmt (par_exit_bb))))
@@ -774,7 +782,7 @@ use_pointer_for_field (tree decl, omp_context *shared_ctx)
                  break;
 
              if (c)
                  break;
 
              if (c)
-               return true;
+               goto maybe_mark_addressable_and_ret;
            }
        }
 
            }
        }
 
@@ -784,7 +792,9 @@ use_pointer_for_field (tree decl, omp_context *shared_ctx)
         returns, the task hasn't necessarily terminated.  */
       if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
        {
         returns, the task hasn't necessarily terminated.  */
       if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
        {
-         tree outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
+         tree outer;
+       maybe_mark_addressable_and_ret:
+         outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
          if (is_gimple_reg (outer))
            {
              /* Taking address of OUTER in lower_send_shared_vars
          if (is_gimple_reg (outer))
            {
              /* Taking address of OUTER in lower_send_shared_vars
@@ -829,7 +839,7 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
   tree copy = copy_var_decl (var, name, type);
 
   DECL_CONTEXT (copy) = current_function_decl;
   tree copy = copy_var_decl (var, name, type);
 
   DECL_CONTEXT (copy) = current_function_decl;
-  TREE_CHAIN (copy) = ctx->block_vars;
+  DECL_CHAIN (copy) = ctx->block_vars;
   ctx->block_vars = copy;
 
   return copy;
   ctx->block_vars = copy;
 
   return copy;
@@ -854,10 +864,10 @@ build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
   if (x != NULL)
     field = x;
 
   if (x != NULL)
     field = x;
 
-  x = build_fold_indirect_ref (ctx->receiver_decl);
+  x = build_simple_mem_ref (ctx->receiver_decl);
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
   if (by_ref)
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
   if (by_ref)
-    x = build_fold_indirect_ref (x);
+    x = build_simple_mem_ref (x);
 
   return x;
 }
 
   return x;
 }
@@ -877,7 +887,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
     {
       x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
       x = build_outer_var_ref (x, ctx);
     {
       x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
       x = build_outer_var_ref (x, ctx);
-      x = build_fold_indirect_ref (x);
+      x = build_simple_mem_ref (x);
     }
   else if (is_taskreg_ctx (ctx))
     {
     }
   else if (is_taskreg_ctx (ctx))
     {
@@ -894,7 +904,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
     gcc_unreachable ();
 
   if (is_reference (var))
     gcc_unreachable ();
 
   if (is_reference (var))
-    x = build_fold_indirect_ref (x);
+    x = build_simple_mem_ref (x);
 
   return x;
 }
 
   return x;
 }
@@ -1091,7 +1101,7 @@ dump_omp_region (FILE *file, struct omp_region *region, int indent)
       fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
               region->cont->index);
     }
       fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
               region->cont->index);
     }
-    
+
   if (region->exit)
     fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
             region->exit->index);
   if (region->exit)
     fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
             region->exit->index);
@@ -1102,13 +1112,13 @@ dump_omp_region (FILE *file, struct omp_region *region, int indent)
     dump_omp_region (file, region->next, indent);
 }
 
     dump_omp_region (file, region->next, indent);
 }
 
-void
+DEBUG_FUNCTION void
 debug_omp_region (struct omp_region *region)
 {
   dump_omp_region (stderr, region, 0);
 }
 
 debug_omp_region (struct omp_region *region)
 {
   dump_omp_region (stderr, region, 0);
 }
 
-void
+DEBUG_FUNCTION void
 debug_all_omp_regions (void)
 {
   dump_omp_region (stderr, root_omp_region, 0);
 debug_all_omp_regions (void)
 {
   dump_omp_region (stderr, root_omp_region, 0);
@@ -1198,11 +1208,12 @@ new_omp_context (gimple stmt, omp_context *outer_ctx)
     {
       ctx->cb.src_fn = current_function_decl;
       ctx->cb.dst_fn = current_function_decl;
     {
       ctx->cb.src_fn = current_function_decl;
       ctx->cb.dst_fn = current_function_decl;
-      ctx->cb.src_node = cgraph_node (current_function_decl);
+      ctx->cb.src_node = cgraph_get_node (current_function_decl);
+      gcc_checking_assert (ctx->cb.src_node);
       ctx->cb.dst_node = ctx->cb.src_node;
       ctx->cb.src_cfun = cfun;
       ctx->cb.copy_decl = omp_copy_decl;
       ctx->cb.dst_node = ctx->cb.src_node;
       ctx->cb.src_cfun = cfun;
       ctx->cb.copy_decl = omp_copy_decl;
-      ctx->cb.eh_region = -1;
+      ctx->cb.eh_lp_nr = 0;
       ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
       ctx->depth = 1;
     }
       ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
       ctx->depth = 1;
     }
@@ -1237,7 +1248,7 @@ finalize_task_copyfn (gimple task_stmt)
   old_fn = current_function_decl;
   push_cfun (child_cfun);
   current_function_decl = child_fn;
   old_fn = current_function_decl;
   push_cfun (child_cfun);
   current_function_decl = child_fn;
-  bind = gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
+  bind = gimplify_body (child_fn, false);
   seq = gimple_seq_alloc ();
   gimple_seq_add_stmt (&seq, bind);
   new_seq = maybe_catch_exception (seq);
   seq = gimple_seq_alloc ();
   gimple_seq_add_stmt (&seq, bind);
   new_seq = maybe_catch_exception (seq);
@@ -1274,13 +1285,13 @@ delete_omp_context (splay_tree_value value)
   if (ctx->record_type)
     {
       tree t;
   if (ctx->record_type)
     {
       tree t;
-      for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
+      for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
        DECL_ABSTRACT_ORIGIN (t) = NULL;
     }
   if (ctx->srecord_type)
     {
       tree t;
        DECL_ABSTRACT_ORIGIN (t) = NULL;
     }
   if (ctx->srecord_type)
     {
       tree t;
-      for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = TREE_CHAIN (t))
+      for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
        DECL_ABSTRACT_ORIGIN (t) = NULL;
     }
 
        DECL_ABSTRACT_ORIGIN (t) = NULL;
     }
 
@@ -1302,7 +1313,7 @@ fixup_child_record_type (omp_context *ctx)
      variably_modified_type_p doesn't work the way we expect for
      record types.  Testing each field for whether it needs remapping
      and creating a new record by hand works, however.  */
      variably_modified_type_p doesn't work the way we expect for
      record types.  Testing each field for whether it needs remapping
      and creating a new record by hand works, however.  */
-  for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
+  for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
       break;
   if (f)
     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
       break;
   if (f)
@@ -1315,12 +1326,12 @@ fixup_child_record_type (omp_context *ctx)
                         TYPE_DECL, name, type);
       TYPE_NAME (type) = name;
 
                         TYPE_DECL, name, type);
       TYPE_NAME (type) = name;
 
-      for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
+      for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
        {
          tree new_f = copy_node (f);
          DECL_CONTEXT (new_f) = type;
          TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
        {
          tree new_f = copy_node (f);
          DECL_CONTEXT (new_f) = type;
          TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
-         TREE_CHAIN (new_f) = new_fields;
+         DECL_CHAIN (new_f) = new_fields;
          walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
          walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
                     &ctx->cb, NULL);
          walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
          walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
                     &ctx->cb, NULL);
@@ -1423,10 +1434,6 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
          break;
 
        case OMP_CLAUSE_COPYPRIVATE:
          break;
 
        case OMP_CLAUSE_COPYPRIVATE:
-         if (ctx->outer)
-           scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
-         /* FALLTHRU */
-
        case OMP_CLAUSE_COPYIN:
          decl = OMP_CLAUSE_DECL (c);
          by_ref = use_pointer_for_field (decl, NULL);
        case OMP_CLAUSE_COPYIN:
          decl = OMP_CLAUSE_DECL (c);
          by_ref = use_pointer_for_field (decl, NULL);
@@ -1437,6 +1444,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
          ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
          break;
 
          ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
          break;
 
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
@@ -1448,6 +1456,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
          break;
 
        default:
@@ -1498,6 +1507,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
          break;
 
        default:
@@ -1525,22 +1536,8 @@ static GTY(()) unsigned int tmp_ompfn_id_num;
 static tree
 create_omp_child_function_name (bool task_copy)
 {
 static tree
 create_omp_child_function_name (bool task_copy)
 {
-  tree name = DECL_ASSEMBLER_NAME (current_function_decl);
-  size_t len = IDENTIFIER_LENGTH (name);
-  char *tmp_name, *prefix;
-  const char *suffix;
-
-  suffix = task_copy ? "_omp_cpyfn" : "_omp_fn";
-  prefix = XALLOCAVEC (char, len + strlen (suffix) + 1);
-  memcpy (prefix, IDENTIFIER_POINTER (name), len);
-  strcpy (prefix + len, suffix);
-#ifndef NO_DOT_IN_LABEL
-  prefix[len] = '.';
-#elif !defined NO_DOLLAR_IN_LABEL
-  prefix[len] = '$';
-#endif
-  ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
-  return get_identifier (tmp_name);
+  return (clone_function_name (current_function_decl,
+                              task_copy ? "_omp_cpyfn" : "_omp_fn"));
 }
 
 /* Build a decl for the omp child function.  It'll not contain a body
 }
 
 /* Build a decl for the omp child function.  It'll not contain a body
@@ -1560,7 +1557,6 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
 
   decl = build_decl (gimple_location (ctx->stmt),
                     FUNCTION_DECL, name, type);
 
   decl = build_decl (gimple_location (ctx->stmt),
                     FUNCTION_DECL, name, type);
-  decl = lang_hooks.decls.pushdecl (decl);
 
   if (!task_copy)
     ctx->cb.dst_fn = decl;
 
   if (!task_copy)
     ctx->cb.dst_fn = decl;
@@ -1570,6 +1566,7 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
   TREE_STATIC (decl) = 1;
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   TREE_STATIC (decl) = 1;
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
+  DECL_NAMELESS (decl) = 1;
   DECL_IGNORED_P (decl) = 0;
   TREE_PUBLIC (decl) = 0;
   DECL_UNINLINABLE (decl) = 1;
   DECL_IGNORED_P (decl) = 0;
   TREE_PUBLIC (decl) = 0;
   DECL_UNINLINABLE (decl) = 1;
@@ -1587,6 +1584,7 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
   t = build_decl (DECL_SOURCE_LOCATION (decl),
                  PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
   DECL_ARTIFICIAL (t) = 1;
   t = build_decl (DECL_SOURCE_LOCATION (decl),
                  PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
   DECL_ARTIFICIAL (t) = 1;
+  DECL_NAMELESS (t) = 1;
   DECL_ARG_TYPE (t) = ptr_type_node;
   DECL_CONTEXT (t) = current_function_decl;
   TREE_USED (t) = 1;
   DECL_ARG_TYPE (t) = ptr_type_node;
   DECL_CONTEXT (t) = current_function_decl;
   TREE_USED (t) = 1;
@@ -1599,15 +1597,16 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
                      PARM_DECL, get_identifier (".omp_data_o"),
                      ptr_type_node);
       DECL_ARTIFICIAL (t) = 1;
                      PARM_DECL, get_identifier (".omp_data_o"),
                      ptr_type_node);
       DECL_ARTIFICIAL (t) = 1;
+      DECL_NAMELESS (t) = 1;
       DECL_ARG_TYPE (t) = ptr_type_node;
       DECL_CONTEXT (t) = current_function_decl;
       TREE_USED (t) = 1;
       TREE_ADDRESSABLE (t) = 1;
       DECL_ARG_TYPE (t) = ptr_type_node;
       DECL_CONTEXT (t) = current_function_decl;
       TREE_USED (t) = 1;
       TREE_ADDRESSABLE (t) = 1;
-      TREE_CHAIN (t) = DECL_ARGUMENTS (decl);
+      DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
       DECL_ARGUMENTS (decl) = t;
     }
 
       DECL_ARGUMENTS (decl) = t;
     }
 
-  /* Allocate memory for the function structure.  The call to 
+  /* Allocate memory for the function structure.  The call to
      allocate_struct_function clobbers CFUN, so we need to restore
      it afterward.  */
   push_struct_function (decl);
      allocate_struct_function clobbers CFUN, so we need to restore
      it afterward.  */
   push_struct_function (decl);
@@ -1645,6 +1644,8 @@ scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
   name = create_tmp_var_name (".omp_data_s");
   name = build_decl (gimple_location (stmt),
                     TYPE_DECL, name, ctx->record_type);
   name = create_tmp_var_name (".omp_data_s");
   name = build_decl (gimple_location (stmt),
                     TYPE_DECL, name, ctx->record_type);
+  DECL_ARTIFICIAL (name) = 1;
+  DECL_NAMELESS (name) = 1;
   TYPE_NAME (ctx->record_type) = name;
   create_omp_child_function (ctx, false);
   gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
   TYPE_NAME (ctx->record_type) = name;
   create_omp_child_function (ctx, false);
   gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
@@ -1669,6 +1670,7 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
   omp_context *ctx;
   tree name, t;
   gimple stmt = gsi_stmt (*gsi);
   omp_context *ctx;
   tree name, t;
   gimple stmt = gsi_stmt (*gsi);
+  location_t loc = gimple_location (stmt);
 
   /* Ignore task directives with empty bodies.  */
   if (optimize > 0
 
   /* Ignore task directives with empty bodies.  */
   if (optimize > 0
@@ -1687,6 +1689,8 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
   name = create_tmp_var_name (".omp_data_s");
   name = build_decl (gimple_location (stmt),
                     TYPE_DECL, name, ctx->record_type);
   name = create_tmp_var_name (".omp_data_s");
   name = build_decl (gimple_location (stmt),
                     TYPE_DECL, name, ctx->record_type);
+  DECL_ARTIFICIAL (name) = 1;
+  DECL_NAMELESS (name) = 1;
   TYPE_NAME (ctx->record_type) = name;
   create_omp_child_function (ctx, false);
   gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
   TYPE_NAME (ctx->record_type) = name;
   create_omp_child_function (ctx, false);
   gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
@@ -1698,6 +1702,8 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
       name = create_tmp_var_name (".omp_data_a");
       name = build_decl (gimple_location (stmt),
                         TYPE_DECL, name, ctx->srecord_type);
       name = create_tmp_var_name (".omp_data_a");
       name = build_decl (gimple_location (stmt),
                         TYPE_DECL, name, ctx->srecord_type);
+      DECL_ARTIFICIAL (name) = 1;
+      DECL_NAMELESS (name) = 1;
       TYPE_NAME (ctx->srecord_type) = name;
       create_omp_child_function (ctx, true);
     }
       TYPE_NAME (ctx->srecord_type) = name;
       create_omp_child_function (ctx, true);
     }
@@ -1727,13 +1733,13 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
            q = &TREE_CHAIN (*q);
          }
        else
            q = &TREE_CHAIN (*q);
          }
        else
-         p = &TREE_CHAIN (*p);
+         p = &DECL_CHAIN (*p);
       *p = vla_fields;
       layout_type (ctx->record_type);
       fixup_child_record_type (ctx);
       if (ctx->srecord_type)
        layout_type (ctx->srecord_type);
       *p = vla_fields;
       layout_type (ctx->record_type);
       fixup_child_record_type (ctx);
       if (ctx->srecord_type)
        layout_type (ctx->srecord_type);
-      t = fold_convert (long_integer_type_node,
+      t = fold_convert_loc (loc, long_integer_type_node,
                        TYPE_SIZE_UNIT (ctx->record_type));
       gimple_omp_task_set_arg_size (stmt, t);
       t = build_int_cst (long_integer_type_node,
                        TYPE_SIZE_UNIT (ctx->record_type));
       gimple_omp_task_set_arg_size (stmt, t);
       t = build_int_cst (long_integer_type_node,
@@ -1924,7 +1930,18 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
        {
          *walk_subtrees = 1;
          if (ctx)
        {
          *walk_subtrees = 1;
          if (ctx)
-           TREE_TYPE (t) = remap_type (TREE_TYPE (t), &ctx->cb);
+           {
+             tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
+             if (tem != TREE_TYPE (t))
+               {
+                 if (TREE_CODE (t) == INTEGER_CST)
+                   *tp = build_int_cst_wide (tem,
+                                             TREE_INT_CST_LOW (t),
+                                             TREE_INT_CST_HIGH (t));
+                 else
+                   TREE_TYPE (t) = tem;
+               }
+           }
        }
       break;
     }
        }
       break;
     }
@@ -2004,7 +2021,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
        *handled_ops_p = false;
        if (ctx)
 
        *handled_ops_p = false;
        if (ctx)
-         for (var = gimple_bind_vars (stmt); var ; var = TREE_CHAIN (var))
+         for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
            insert_decl_map (&ctx->cb, var, var);
       }
       break;
            insert_decl_map (&ctx->cb, var, var);
       }
       break;
@@ -2043,7 +2060,7 @@ scan_omp (gimple_seq body, omp_context *ctx)
 static tree
 build_omp_barrier (void)
 {
 static tree
 build_omp_barrier (void)
 {
-  return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
+  return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
 }
 
 /* If a context was created for STMT when it was scanned, return it.  */
 }
 
 /* If a context was created for STMT when it was scanned, return it.  */
@@ -2142,6 +2159,7 @@ maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
 tree
 omp_reduction_init (tree clause, tree type)
 {
 tree
 omp_reduction_init (tree clause, tree type)
 {
+  location_t loc = OMP_CLAUSE_LOCATION (clause);
   switch (OMP_CLAUSE_REDUCTION_CODE (clause))
     {
     case PLUS_EXPR:
   switch (OMP_CLAUSE_REDUCTION_CODE (clause))
     {
     case PLUS_EXPR:
@@ -2152,16 +2170,16 @@ omp_reduction_init (tree clause, tree type)
     case TRUTH_ORIF_EXPR:
     case TRUTH_XOR_EXPR:
     case NE_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_XOR_EXPR:
     case NE_EXPR:
-      return fold_convert (type, integer_zero_node);
+      return build_zero_cst (type);
 
     case MULT_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_ANDIF_EXPR:
     case EQ_EXPR:
 
     case MULT_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_ANDIF_EXPR:
     case EQ_EXPR:
-      return fold_convert (type, integer_one_node);
+      return fold_convert_loc (loc, type, integer_one_node);
 
     case BIT_AND_EXPR:
 
     case BIT_AND_EXPR:
-      return fold_convert (type, integer_minus_one_node);
+      return fold_convert_loc (loc, type, integer_minus_one_node);
 
     case MAX_EXPR:
       if (SCALAR_FLOAT_TYPE_P (type))
 
     case MAX_EXPR:
       if (SCALAR_FLOAT_TYPE_P (type))
@@ -2224,7 +2242,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 
   /* Do all the fixed sized types in the first pass, and the variable sized
      types in the second pass.  This makes sure that the scalar arguments to
 
   /* Do all the fixed sized types in the first pass, and the variable sized
      types in the second pass.  This makes sure that the scalar arguments to
-     the variable sized types are processed before we use them in the 
+     the variable sized types are processed before we use them in the
      variable sized operations.  */
   for (pass = 0; pass < 2; ++pass)
     {
      variable sized operations.  */
   for (pass = 0; pass < 2; ++pass)
     {
@@ -2233,6 +2251,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
          enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
          tree var, new_var;
          bool by_ref;
          enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
          tree var, new_var;
          bool by_ref;
+         location_t clause_loc = OMP_CLAUSE_LOCATION (c);
 
          switch (c_kind)
            {
 
          switch (c_kind)
            {
@@ -2282,7 +2301,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
              if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
                {
                  gimple stmt;
              if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
                {
                  gimple stmt;
-                 tree tmp;
+                 tree tmp, atmp;
 
                  ptr = DECL_VALUE_EXPR (new_var);
                  gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
 
                  ptr = DECL_VALUE_EXPR (new_var);
                  gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
@@ -2291,15 +2310,15 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
                  x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
 
                  /* void *tmp = __builtin_alloca */
                  x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
 
                  /* void *tmp = __builtin_alloca */
-                 stmt
-                   = gimple_build_call (built_in_decls[BUILT_IN_ALLOCA], 1, x);
+                 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
+                 stmt = gimple_build_call (atmp, 1, x);
                  tmp = create_tmp_var_raw (ptr_type_node, NULL);
                  gimple_add_tmp_var (tmp);
                  gimple_call_set_lhs (stmt, tmp);
 
                  gimple_seq_add_stmt (ilist, stmt);
 
                  tmp = create_tmp_var_raw (ptr_type_node, NULL);
                  gimple_add_tmp_var (tmp);
                  gimple_call_set_lhs (stmt, tmp);
 
                  gimple_seq_add_stmt (ilist, stmt);
 
-                 x = fold_convert (TREE_TYPE (ptr), tmp);
+                 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
                  gimplify_assign (ptr, x, ilist);
                }
            }
                  gimplify_assign (ptr, x, ilist);
                }
            }
@@ -2320,7 +2339,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
              if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
                {
                  x = build_receiver_ref (var, false, ctx);
              if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
                {
                  x = build_receiver_ref (var, false, ctx);
-                 x = build_fold_addr_expr (x);
+                 x = build_fold_addr_expr_loc (clause_loc, x);
                }
              else if (TREE_CONSTANT (x))
                {
                }
              else if (TREE_CONSTANT (x))
                {
@@ -2332,17 +2351,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
                                          name);
                  gimple_add_tmp_var (x);
                  TREE_ADDRESSABLE (x) = 1;
                                          name);
                  gimple_add_tmp_var (x);
                  TREE_ADDRESSABLE (x) = 1;
-                 x = build_fold_addr_expr (x);
+                 x = build_fold_addr_expr_loc (clause_loc, x);
                }
              else
                {
                }
              else
                {
-                 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
+                 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
+                 x = build_call_expr_loc (clause_loc, atmp, 1, x);
                }
 
                }
 
-             x = fold_convert (TREE_TYPE (new_var), x);
+             x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
              gimplify_assign (new_var, x, ilist);
 
              gimplify_assign (new_var, x, ilist);
 
-             new_var = build_fold_indirect_ref (new_var);
+             new_var = build_simple_mem_ref_loc (clause_loc, new_var);
            }
          else if (c_kind == OMP_CLAUSE_REDUCTION
                   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
            }
          else if (c_kind == OMP_CLAUSE_REDUCTION
                   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
@@ -2370,7 +2390,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
              /* ??? If VAR is not passed by reference, and the variable
                 hasn't been initialized yet, then we'll get a warning for
                 the store into the omp_data_s structure.  Ideally, we'd be
              /* ??? If VAR is not passed by reference, and the variable
                 hasn't been initialized yet, then we'll get a warning for
                 the store into the omp_data_s structure.  Ideally, we'd be
-                able to notice this and not store anything at all, but 
+                able to notice this and not store anything at all, but
                 we're generating code too early.  Suppress the warning.  */
              if (!by_ref)
                TREE_NO_WARNING (var) = 1;
                 we're generating code too early.  Suppress the warning.  */
              if (!by_ref)
                TREE_NO_WARNING (var) = 1;
@@ -2446,7 +2466,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
                  x = build_outer_var_ref (var, ctx);
 
                  if (is_reference (var))
                  x = build_outer_var_ref (var, ctx);
 
                  if (is_reference (var))
-                   x = build_fold_addr_expr (x);
+                   x = build_fold_addr_expr_loc (clause_loc, x);
                  SET_DECL_VALUE_EXPR (placeholder, x);
                  DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
                  lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
                  SET_DECL_VALUE_EXPR (placeholder, x);
                  DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
                  lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
@@ -2474,7 +2494,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
      but it certainly is to C++ operator=.  */
   if (copyin_seq)
     {
      but it certainly is to C++ operator=.  */
   if (copyin_seq)
     {
-      x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+      x = build_call_expr (builtin_decl_explicit (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);
       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);
@@ -2543,6 +2564,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
   for (c = clauses; c ;)
     {
       tree var, new_var;
   for (c = clauses; c ;)
     {
       tree var, new_var;
+      location_t clause_loc = OMP_CLAUSE_LOCATION (c);
 
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
        {
 
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
        {
@@ -2559,7 +2581,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
 
          x = build_outer_var_ref (var, ctx);
          if (is_reference (var))
 
          x = build_outer_var_ref (var, ctx);
          if (is_reference (var))
-           new_var = build_fold_indirect_ref (new_var);
+           new_var = build_simple_mem_ref_loc (clause_loc, new_var);
          x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
          gimplify_and_add (x, stmt_list);
        }
          x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
          gimplify_and_add (x, stmt_list);
        }
@@ -2618,6 +2640,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
     {
       tree var, ref, new_var;
       enum tree_code code;
     {
       tree var, ref, new_var;
       enum tree_code code;
+      location_t clause_loc = OMP_CLAUSE_LOCATION (c);
 
       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
        continue;
 
       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
        continue;
@@ -2625,7 +2648,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
       var = OMP_CLAUSE_DECL (c);
       new_var = lookup_decl (var, ctx);
       if (is_reference (var))
       var = OMP_CLAUSE_DECL (c);
       new_var = lookup_decl (var, ctx);
       if (is_reference (var))
-       new_var = build_fold_indirect_ref (new_var);
+       new_var = build_simple_mem_ref_loc (clause_loc, new_var);
       ref = build_outer_var_ref (var, ctx);
       code = OMP_CLAUSE_REDUCTION_CODE (c);
 
       ref = build_outer_var_ref (var, ctx);
       code = OMP_CLAUSE_REDUCTION_CODE (c);
 
@@ -2636,11 +2659,11 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
 
       if (count == 1)
        {
 
       if (count == 1)
        {
-         tree addr = build_fold_addr_expr (ref);
+         tree addr = build_fold_addr_expr_loc (clause_loc, ref);
 
          addr = save_expr (addr);
          ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
 
          addr = save_expr (addr);
          ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
-         x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
+         x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
          x = build2 (OMP_ATOMIC, void_type_node, addr, x);
          gimplify_and_add (x, stmt_seqp);
          return;
          x = build2 (OMP_ATOMIC, void_type_node, addr, x);
          gimplify_and_add (x, stmt_seqp);
          return;
@@ -2651,7 +2674,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
          tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
 
          if (is_reference (var))
          tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
 
          if (is_reference (var))
-           ref = build_fold_addr_expr (ref);
+           ref = build_fold_addr_expr_loc (clause_loc, ref);
          SET_DECL_VALUE_EXPR (placeholder, ref);
          DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
          lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
          SET_DECL_VALUE_EXPR (placeholder, ref);
          DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
          lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
@@ -2667,12 +2690,14 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
        }
     }
 
        }
     }
 
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
+  stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
+                           0);
   gimple_seq_add_stmt (stmt_seqp, stmt);
 
   gimple_seq_add_seq (stmt_seqp, sub_seq);
 
   gimple_seq_add_stmt (stmt_seqp, stmt);
 
   gimple_seq_add_seq (stmt_seqp, sub_seq);
 
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
+  stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
+                           0);
   gimple_seq_add_stmt (stmt_seqp, stmt);
 }
 
   gimple_seq_add_stmt (stmt_seqp, stmt);
 }
 
@@ -2687,8 +2712,9 @@ lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     {
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     {
-      tree var, ref, x;
+      tree var, new_var, ref, x;
       bool by_ref;
       bool by_ref;
+      location_t clause_loc = OMP_CLAUSE_LOCATION (c);
 
       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
        continue;
 
       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
        continue;
@@ -2697,17 +2723,29 @@ lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
       by_ref = use_pointer_for_field (var, NULL);
 
       ref = build_sender_ref (var, ctx);
       by_ref = use_pointer_for_field (var, NULL);
 
       ref = build_sender_ref (var, ctx);
-      x = lookup_decl_in_outer_ctx (var, ctx);
-      x = by_ref ? build_fold_addr_expr (x) : x;
+      x = new_var = lookup_decl_in_outer_ctx (var, ctx);
+      if (by_ref)
+       {
+         x = build_fold_addr_expr_loc (clause_loc, new_var);
+         x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
+       }
       gimplify_assign (ref, x, slist);
 
       gimplify_assign (ref, x, slist);
 
-      ref = build_receiver_ref (var, by_ref, ctx);
+      ref = build_receiver_ref (var, false, ctx);
+      if (by_ref)
+       {
+         ref = fold_convert_loc (clause_loc,
+                                 build_pointer_type (TREE_TYPE (new_var)),
+                                 ref);
+         ref = build_fold_indirect_ref_loc (clause_loc, ref);
+       }
       if (is_reference (var))
        {
       if (is_reference (var))
        {
-         ref = build_fold_indirect_ref (ref);
-         var = build_fold_indirect_ref (var);
+         ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
+         ref = build_simple_mem_ref_loc (clause_loc, ref);
+         new_var = build_simple_mem_ref_loc (clause_loc, new_var);
        }
        }
-      x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
+      x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
       gimplify_and_add (x, rlist);
     }
 }
       gimplify_and_add (x, rlist);
     }
 }
@@ -2726,6 +2764,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
     {
       tree val, ref, x, var;
       bool by_ref, do_in = false, do_out = false;
     {
       tree val, ref, x, var;
       bool by_ref, do_in = false, do_out = false;
+      location_t clause_loc = OMP_CLAUSE_LOCATION (c);
 
       switch (OMP_CLAUSE_CODE (c))
        {
 
       switch (OMP_CLAUSE_CODE (c))
        {
@@ -2787,7 +2826,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
       if (do_in)
        {
          ref = build_sender_ref (val, ctx);
       if (do_in)
        {
          ref = build_sender_ref (val, ctx);
-         x = by_ref ? build_fold_addr_expr (var) : var;
+         x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
          gimplify_assign (ref, x, ilist);
          if (is_task_ctx (ctx))
            DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
          gimplify_assign (ref, x, ilist);
          if (is_task_ctx (ctx))
            DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
@@ -2814,7 +2853,7 @@ lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
     return;
 
   record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
     return;
 
   record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
-  for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
+  for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
     {
       ovar = DECL_ABSTRACT_ORIGIN (f);
       nvar = maybe_lookup_decl (ovar, ctx);
     {
       ovar = DECL_ABSTRACT_ORIGIN (f);
       nvar = maybe_lookup_decl (ovar, ctx);
@@ -2868,7 +2907,7 @@ gimple_build_cond_empty (tree cond)
 }
 
 
 }
 
 
-/* Build the function calls to GOMP_parallel_start etc to actually 
+/* Build the function calls to GOMP_parallel_start etc to actually
    generate the parallel operation.  REGION is the parallel region
    being expanded.  BB is the block where to insert the code.  WS_ARGS
    will be set if this is a call to a combined parallel+workshare
    generate the parallel operation.  REGION is the parallel region
    being expanded.  BB is the block where to insert the code.  WS_ARGS
    will be set if this is a call to a combined parallel+workshare
@@ -2877,12 +2916,15 @@ gimple_build_cond_empty (tree cond)
 
 static void
 expand_parallel_call (struct omp_region *region, basic_block bb,
 
 static void
 expand_parallel_call (struct omp_region *region, basic_block bb,
-                     gimple entry_stmt, tree ws_args)
+                     gimple entry_stmt, VEC(tree,gc) *ws_args)
 {
   tree t, t1, t2, val, cond, c, clauses;
   gimple_stmt_iterator gsi;
   gimple stmt;
 {
   tree t, t1, t2, val, cond, c, clauses;
   gimple_stmt_iterator gsi;
   gimple stmt;
-  int start_ix;
+  enum built_in_function start_ix;
+  int start_ix2;
+  location_t clause_loc;
+  VEC(tree,gc) *args;
 
   clauses = gimple_omp_parallel_clauses (entry_stmt);
 
 
   clauses = gimple_omp_parallel_clauses (entry_stmt);
 
@@ -2895,10 +2937,11 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
        {
        case GIMPLE_OMP_FOR:
          gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
        {
        case GIMPLE_OMP_FOR:
          gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
-         start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
-                    + (region->inner->sched_kind
-                       == OMP_CLAUSE_SCHEDULE_RUNTIME
-                       ? 3 : region->inner->sched_kind);
+         start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
+                      + (region->inner->sched_kind
+                         == OMP_CLAUSE_SCHEDULE_RUNTIME
+                         ? 3 : region->inner->sched_kind));
+         start_ix = (enum built_in_function)start_ix2;
          break;
        case GIMPLE_OMP_SECTIONS:
          start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
          break;
        case GIMPLE_OMP_SECTIONS:
          start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
@@ -2919,10 +2962,15 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
 
   c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
   if (c)
 
   c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
   if (c)
-    val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
+    {
+      val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
+      clause_loc = OMP_CLAUSE_LOCATION (c);
+    }
+  else
+    clause_loc = gimple_location (entry_stmt);
 
   /* Ensure 'val' is of the correct type.  */
 
   /* Ensure 'val' is of the correct type.  */
-  val = fold_convert (unsigned_type_node, val);
+  val = fold_convert_loc (clause_loc, unsigned_type_node, val);
 
   /* If we found the clause 'if (cond)', build either
      (cond != 0) or (cond ? val : 1u).  */
 
   /* If we found the clause 'if (cond)', build either
      (cond != 0) or (cond ? val : 1u).  */
@@ -2933,7 +2981,8 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
       cond = gimple_boolify (cond);
 
       if (integer_zerop (val))
       cond = gimple_boolify (cond);
 
       if (integer_zerop (val))
-       val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
+       val = fold_build2_loc (clause_loc,
+                          EQ_EXPR, unsigned_type_node, cond,
                           build_int_cst (TREE_TYPE (cond), 0));
       else
        {
                           build_int_cst (TREE_TYPE (cond), 0));
       else
        {
@@ -2987,8 +3036,8 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
            {
              gimple phi = create_phi_node (tmp_join, bb);
              SSA_NAME_DEF_STMT (tmp_join) = phi;
            {
              gimple phi = create_phi_node (tmp_join, bb);
              SSA_NAME_DEF_STMT (tmp_join) = phi;
-             add_phi_arg (phi, tmp_then, e_then);
-             add_phi_arg (phi, tmp_else, e_else);
+             add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
+             add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
            }
 
          val = tmp_join;
            }
 
          val = tmp_join;
@@ -3007,15 +3056,14 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
     t1 = build_fold_addr_expr (t);
   t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
 
     t1 = build_fold_addr_expr (t);
   t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
 
-  if (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);
+  args = VEC_alloc (tree, gc, 3 + VEC_length (tree, ws_args));
+  VEC_quick_push (tree, args, t2);
+  VEC_quick_push (tree, args, t1);
+  VEC_quick_push (tree, args, val);
+  VEC_splice (tree, args, ws_args);
+
+  t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
+                              builtin_decl_explicit (start_ix), args);
 
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                            false, GSI_CONTINUE_LINKING);
 
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                            false, GSI_CONTINUE_LINKING);
@@ -3025,11 +3073,14 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
     t = null_pointer_node;
   else
     t = build_fold_addr_expr (t);
     t = null_pointer_node;
   else
     t = build_fold_addr_expr (t);
-  t = build_call_expr (gimple_omp_parallel_child_fn (entry_stmt), 1, t);
+  t = build_call_expr_loc (gimple_location (entry_stmt),
+                          gimple_omp_parallel_child_fn (entry_stmt), 1, t);
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                            false, GSI_CONTINUE_LINKING);
 
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                            false, GSI_CONTINUE_LINKING);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
+  t = build_call_expr_loc (gimple_location (entry_stmt),
+                          builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
+                          0);
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                            false, GSI_CONTINUE_LINKING);
 }
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                            false, GSI_CONTINUE_LINKING);
 }
@@ -3041,8 +3092,9 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
 static void
 expand_task_call (basic_block bb, gimple entry_stmt)
 {
 static void
 expand_task_call (basic_block bb, gimple entry_stmt)
 {
-  tree t, t1, t2, t3, flags, cond, c, clauses;
+  tree t, t1, t2, t3, flags, cond, c, c2, clauses;
   gimple_stmt_iterator gsi;
   gimple_stmt_iterator gsi;
+  location_t loc = gimple_location (entry_stmt);
 
   clauses = gimple_omp_task_clauses (entry_stmt);
 
 
   clauses = gimple_omp_task_clauses (entry_stmt);
 
@@ -3053,22 +3105,35 @@ expand_task_call (basic_block bb, gimple entry_stmt)
     cond = boolean_true_node;
 
   c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
     cond = boolean_true_node;
 
   c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
-  flags = build_int_cst (unsigned_type_node, (c ? 1 : 0));
+  c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
+  flags = build_int_cst (unsigned_type_node,
+                        (c ? 1 : 0) + (c2 ? 4 : 0));
+
+  c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
+  if (c)
+    {
+      c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
+      c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
+                          build_int_cst (unsigned_type_node, 2),
+                          build_int_cst (unsigned_type_node, 0));
+      flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
+    }
 
   gsi = gsi_last_bb (bb);
   t = gimple_omp_task_data_arg (entry_stmt);
   if (t == NULL)
     t2 = null_pointer_node;
   else
 
   gsi = gsi_last_bb (bb);
   t = gimple_omp_task_data_arg (entry_stmt);
   if (t == NULL)
     t2 = null_pointer_node;
   else
-    t2 = build_fold_addr_expr (t);
-  t1 = build_fold_addr_expr (gimple_omp_task_child_fn (entry_stmt));
+    t2 = build_fold_addr_expr_loc (loc, t);
+  t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
   t = gimple_omp_task_copy_fn (entry_stmt);
   if (t == NULL)
     t3 = null_pointer_node;
   else
   t = gimple_omp_task_copy_fn (entry_stmt);
   if (t == NULL)
     t3 = null_pointer_node;
   else
-    t3 = build_fold_addr_expr (t);
+    t3 = build_fold_addr_expr_loc (loc, t);
 
 
-  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
+                      7, t1, t2, t3,
                       gimple_omp_task_arg_size (entry_stmt),
                       gimple_omp_task_arg_align (entry_stmt), cond, flags);
 
                       gimple_omp_task_arg_size (entry_stmt),
                       gimple_omp_task_arg_align (entry_stmt), cond, flags);
 
@@ -3084,42 +3149,39 @@ expand_task_call (basic_block bb, gimple entry_stmt)
 static gimple_seq
 maybe_catch_exception (gimple_seq body)
 {
 static gimple_seq
 maybe_catch_exception (gimple_seq body)
 {
-  gimple f, t;
+  gimple g;
+  tree decl;
 
   if (!flag_exceptions)
     return body;
 
 
   if (!flag_exceptions)
     return body;
 
-  if (lang_protect_cleanup_actions)
-    t = lang_protect_cleanup_actions ();
+  if (lang_hooks.eh_protect_cleanup_actions != NULL)
+    decl = lang_hooks.eh_protect_cleanup_actions ();
   else
   else
-    t = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
-
-  f = gimple_build_eh_filter (NULL, gimple_seq_alloc_with_stmt (t));
-  gimple_eh_filter_set_must_not_throw (f, true);
+    decl = builtin_decl_explicit (BUILT_IN_TRAP);
 
 
-  t = gimple_build_try (body, gimple_seq_alloc_with_stmt (f),
+  g = gimple_build_eh_must_not_throw (decl);
+  g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
                        GIMPLE_TRY_CATCH);
 
                        GIMPLE_TRY_CATCH);
 
- return gimple_seq_alloc_with_stmt (t);
+ return gimple_seq_alloc_with_stmt (g);
 }
 
 /* Chain all the DECLs in LIST by their TREE_CHAIN fields.  */
 
 static tree
 }
 
 /* Chain all the DECLs in LIST by their TREE_CHAIN fields.  */
 
 static tree
-list2chain (tree list)
+vec2chain (VEC(tree,gc) *v)
 {
 {
-  tree t;
+  tree chain = NULL_TREE, t;
+  unsigned ix;
 
 
-  for (t = list; t; t = TREE_CHAIN (t))
+  FOR_EACH_VEC_ELT_REVERSE (tree, v, ix, t)
     {
     {
-      tree var = TREE_VALUE (t);
-      if (TREE_CHAIN (t))
-       TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
-      else
-       TREE_CHAIN (var) = NULL_TREE;
+      DECL_CHAIN (t) = chain;
+      chain = t;
     }
 
     }
 
-  return list ? TREE_VALUE (list) : NULL_TREE;
+  return chain;
 }
 
 
 }
 
 
@@ -3178,12 +3240,12 @@ remove_exit_barrier (struct omp_region *region)
            {
              gimple parallel_stmt = last_stmt (region->entry);
              tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
            {
              gimple parallel_stmt = last_stmt (region->entry);
              tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
-             tree local_decls = DECL_STRUCT_FUNCTION (child_fun)->local_decls;
-             tree block;
+             tree local_decls, block, decl;
+             unsigned ix;
 
              any_addressable_vars = 0;
 
              any_addressable_vars = 0;
-             for (; local_decls; local_decls = TREE_CHAIN (local_decls))
-               if (TREE_ADDRESSABLE (TREE_VALUE (local_decls)))
+             FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
+               if (TREE_ADDRESSABLE (decl))
                  {
                    any_addressable_vars = 1;
                    break;
                  {
                    any_addressable_vars = 1;
                    break;
@@ -3196,7 +3258,7 @@ remove_exit_barrier (struct omp_region *region)
                {
                  for (local_decls = BLOCK_VARS (block);
                       local_decls;
                {
                  for (local_decls = BLOCK_VARS (block);
                       local_decls;
-                      local_decls = TREE_CHAIN (local_decls))
+                      local_decls = DECL_CHAIN (local_decls))
                    if (TREE_ADDRESSABLE (local_decls))
                      {
                        any_addressable_vars = 1;
                    if (TREE_ADDRESSABLE (local_decls))
                      {
                        any_addressable_vars = 1;
@@ -3243,10 +3305,10 @@ optimize_omp_library_calls (gimple entry_stmt)
 {
   basic_block bb;
   gimple_stmt_iterator gsi;
 {
   basic_block bb;
   gimple_stmt_iterator gsi;
-  tree thr_num_id
-    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
-  tree num_thr_id
-    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
+  tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+  tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
+  tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
+  tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
   bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
                      && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
                                          OMP_CLAUSE_UNTIED) != NULL);
   bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
                      && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
                                          OMP_CLAUSE_UNTIED) != NULL);
@@ -3271,10 +3333,10 @@ optimize_omp_library_calls (gimple entry_stmt)
                   during the execution of the task region.  */
                if (untied_task)
                  continue;
                   during the execution of the task region.  */
                if (untied_task)
                  continue;
-               built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
+               built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
              }
            else if (DECL_NAME (decl) == num_thr_id)
              }
            else if (DECL_NAME (decl) == num_thr_id)
-             built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
+             built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
            else
              continue;
 
            else
              continue;
 
@@ -3286,8 +3348,8 @@ optimize_omp_library_calls (gimple entry_stmt)
              continue;
 
            if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
              continue;
 
            if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
-               || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
-                  != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
+               || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
+                                       TREE_TYPE (TREE_TYPE (built_in))))
              continue;
 
            gimple_call_set_fndecl (call, built_in);
              continue;
 
            gimple_call_set_fndecl (call, built_in);
@@ -3302,11 +3364,12 @@ expand_omp_taskreg (struct omp_region *region)
 {
   basic_block entry_bb, exit_bb, new_bb;
   struct function *child_cfun;
 {
   basic_block entry_bb, exit_bb, new_bb;
   struct function *child_cfun;
-  tree child_fn, block, t, ws_args, *tp;
+  tree child_fn, block, t;
   tree save_current;
   gimple_stmt_iterator gsi;
   gimple entry_stmt, stmt;
   edge e;
   tree save_current;
   gimple_stmt_iterator gsi;
   gimple entry_stmt, stmt;
   edge e;
+  VEC(tree,gc) *ws_args;
 
   entry_stmt = last_stmt (region->entry);
   child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
 
   entry_stmt = last_stmt (region->entry);
   child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
@@ -3321,7 +3384,7 @@ expand_omp_taskreg (struct omp_region *region)
   if (is_combined_parallel (region))
     ws_args = region->ws_args;
   else
   if (is_combined_parallel (region))
     ws_args = region->ws_args;
   else
-    ws_args = NULL_TREE;
+    ws_args = NULL;
 
   if (child_cfun->cfg)
     {
 
   if (child_cfun->cfg)
     {
@@ -3348,6 +3411,8 @@ expand_omp_taskreg (struct omp_region *region)
     }
   else
     {
     }
   else
     {
+      unsigned srcidx, dstidx, num;
+
       /* If the parallel region needs data sent from the parent
         function, then the very first statement (except possible
         tree profile counter updates) of the parallel body
       /* If the parallel region needs data sent from the parent
         function, then the very first statement (except possible
         tree profile counter updates) of the parallel body
@@ -3425,11 +3490,11 @@ expand_omp_taskreg (struct omp_region *region)
 
       /* Declare local variables needed in CHILD_CFUN.  */
       block = DECL_INITIAL (child_fn);
 
       /* Declare local variables needed in CHILD_CFUN.  */
       block = DECL_INITIAL (child_fn);
-      BLOCK_VARS (block) = list2chain (child_cfun->local_decls);
+      BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
       /* The gimplifier could record temporaries in parallel/task block
         rather than in containing function's local_decls chain,
         which would mean cgraph missed finalizing them.  Do it now.  */
       /* The gimplifier could record temporaries in parallel/task block
         rather than in containing function's local_decls chain,
         which would mean cgraph missed finalizing them.  Do it now.  */
-      for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
+      for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
        if (TREE_CODE (t) == VAR_DECL
            && TREE_STATIC (t)
            && !DECL_EXTERNAL (t))
        if (TREE_CODE (t) == VAR_DECL
            && TREE_STATIC (t)
            && !DECL_EXTERNAL (t))
@@ -3439,7 +3504,7 @@ expand_omp_taskreg (struct omp_region *region)
       TREE_USED (block) = 1;
 
       /* Reset DECL_CONTEXT on function arguments.  */
       TREE_USED (block) = 1;
 
       /* Reset DECL_CONTEXT on function arguments.  */
-      for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
+      for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
        DECL_CONTEXT (t) = child_fn;
 
       /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
        DECL_CONTEXT (t) = child_fn;
 
       /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
@@ -3465,7 +3530,7 @@ expand_omp_taskreg (struct omp_region *region)
        }
 
       /* Move the parallel region into CHILD_CFUN.  */
        }
 
       /* Move the parallel region into CHILD_CFUN.  */
+
       if (gimple_in_ssa_p (cfun))
        {
          push_cfun (child_cfun);
       if (gimple_in_ssa_p (cfun))
        {
          push_cfun (child_cfun);
@@ -3483,11 +3548,18 @@ expand_omp_taskreg (struct omp_region *region)
        single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
 
       /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
        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);
+      num = VEC_length (tree, child_cfun->local_decls);
+      for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
+       {
+         t = VEC_index (tree, child_cfun->local_decls, srcidx);
+         if (DECL_CONTEXT (t) == cfun->decl)
+           continue;
+         if (srcidx != dstidx)
+           VEC_replace (tree, child_cfun->local_decls, dstidx, t);
+         dstidx++;
+       }
+      if (dstidx != num)
+       VEC_truncate (tree, child_cfun->local_decls, dstidx);
 
       /* Inform the callgraph about the new function.  */
       DECL_STRUCT_FUNCTION (child_fn)->curr_properties
 
       /* Inform the callgraph about the new function.  */
       DECL_STRUCT_FUNCTION (child_fn)->curr_properties
@@ -3522,7 +3594,7 @@ expand_omp_taskreg (struct omp_region *region)
       current_function_decl = save_current;
       pop_cfun ();
     }
       current_function_decl = save_current;
       pop_cfun ();
     }
-  
+
   /* Emit a library call to launch the children threads.  */
   if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
     expand_parallel_call (region, new_bb, entry_stmt, ws_args);
   /* Emit a library call to launch the children threads.  */
   if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
     expand_parallel_call (region, new_bb, entry_stmt, ws_args);
@@ -3748,7 +3820,7 @@ expand_omp_for_generic (struct omp_region *region,
     {
       /* In a combined parallel loop, emit a call to
         GOMP_loop_foo_next.  */
     {
       /* In a combined parallel loop, emit a call to
         GOMP_loop_foo_next.  */
-      t = build_call_expr (built_in_decls[next_fn], 2,
+      t = build_call_expr (builtin_decl_explicit (next_fn), 2,
                           build_fold_addr_expr (istart0),
                           build_fold_addr_expr (iend0));
     }
                           build_fold_addr_expr (istart0),
                           build_fold_addr_expr (iend0));
     }
@@ -3784,34 +3856,36 @@ expand_omp_for_generic (struct omp_region *region,
          if (fd->chunk_size)
            {
              t = fold_convert (fd->iter_type, fd->chunk_size);
          if (fd->chunk_size)
            {
              t = fold_convert (fd->iter_type, fd->chunk_size);
-             t = build_call_expr (built_in_decls[start_fn], 6,
-                                  t0, t1, t2, t, t3, t4);
+             t = build_call_expr (builtin_decl_explicit (start_fn),
+                                  6, t0, t1, t2, t, t3, t4);
            }
          else
            }
          else
-           t = build_call_expr (built_in_decls[start_fn], 5,
-                                t0, t1, t2, t3, t4);
+           t = build_call_expr (builtin_decl_explicit (start_fn),
+                                5, t0, t1, t2, t3, t4);
        }
       else
        {
          tree t5;
          tree c_bool_type;
        }
       else
        {
          tree t5;
          tree c_bool_type;
+         tree bfn_decl;
 
          /* The GOMP_loop_ull_*start functions have additional boolean
             argument, true for < loops and false for > loops.
             In Fortran, the C bool type can be different from
             boolean_type_node.  */
 
          /* The GOMP_loop_ull_*start functions have additional boolean
             argument, true for < loops and false for > loops.
             In Fortran, the C bool type can be different from
             boolean_type_node.  */
-         c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn]));
+         bfn_decl = builtin_decl_explicit (start_fn);
+         c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
          t5 = build_int_cst (c_bool_type,
                              fd->loop.cond_code == LT_EXPR ? 1 : 0);
          if (fd->chunk_size)
            {
          t5 = build_int_cst (c_bool_type,
                              fd->loop.cond_code == LT_EXPR ? 1 : 0);
          if (fd->chunk_size)
            {
+             tree bfn_decl = builtin_decl_explicit (start_fn);
              t = fold_convert (fd->iter_type, fd->chunk_size);
              t = fold_convert (fd->iter_type, fd->chunk_size);
-             t = build_call_expr (built_in_decls[start_fn], 7,
-                                  t5, t0, t1, t2, t, t3, t4);
+             t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
            }
          else
            }
          else
-           t = build_call_expr (built_in_decls[start_fn], 6,
-                                t5, t0, t1, t2, t3, t4);
+           t = build_call_expr (builtin_decl_explicit (start_fn),
+                                6, t5, t0, t1, t2, t3, t4);
        }
     }
   if (TREE_TYPE (t) != boolean_type_node)
        }
     }
   if (TREE_TYPE (t) != boolean_type_node)
@@ -3864,8 +3938,7 @@ expand_omp_for_generic (struct omp_region *region,
          t = fold_build2 (MULT_EXPR, itype, t,
                           fold_convert (itype, fd->loops[i].step));
          if (POINTER_TYPE_P (vtype))
          t = fold_build2 (MULT_EXPR, itype, t,
                           fold_convert (itype, fd->loops[i].step));
          if (POINTER_TYPE_P (vtype))
-           t = fold_build2 (POINTER_PLUS_EXPR, vtype,
-                            fd->loops[i].n1, fold_convert (sizetype, t));
+           t = fold_build_pointer_plus (fd->loops[i].n1, t);
          else
            t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
          t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
          else
            t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
          t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
@@ -3894,8 +3967,7 @@ expand_omp_for_generic (struct omp_region *region,
       vback = gimple_omp_continue_control_def (stmt);
 
       if (POINTER_TYPE_P (type))
       vback = gimple_omp_continue_control_def (stmt);
 
       if (POINTER_TYPE_P (type))
-       t = fold_build2 (POINTER_PLUS_EXPR, type, vmain,
-                        fold_convert (sizetype, fd->loop.step));
+       t = fold_build_pointer_plus (vmain, fd->loop.step);
       else
        t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
       t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
       else
        t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
       t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
@@ -3939,9 +4011,7 @@ expand_omp_for_generic (struct omp_region *region,
              set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
 
              if (POINTER_TYPE_P (vtype))
              set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
 
              if (POINTER_TYPE_P (vtype))
-               t = fold_build2 (POINTER_PLUS_EXPR, vtype,
-                                fd->loops[i].v,
-                                fold_convert (sizetype, fd->loops[i].step));
+               t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
              else
                t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
                                 fd->loops[i].step);
              else
                t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
                                 fd->loops[i].step);
@@ -3971,7 +4041,7 @@ expand_omp_for_generic (struct omp_region *region,
       /* Emit code to get the next parallel iteration in L2_BB.  */
       gsi = gsi_start_bb (l2_bb);
 
       /* Emit code to get the next parallel iteration in L2_BB.  */
       gsi = gsi_start_bb (l2_bb);
 
-      t = build_call_expr (built_in_decls[next_fn], 2,
+      t = build_call_expr (builtin_decl_explicit (next_fn), 2,
                           build_fold_addr_expr (istart0),
                           build_fold_addr_expr (iend0));
       t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                           build_fold_addr_expr (istart0),
                           build_fold_addr_expr (iend0));
       t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
@@ -3986,9 +4056,9 @@ expand_omp_for_generic (struct omp_region *region,
   /* Add the loop cleanup function.  */
   gsi = gsi_last_bb (exit_bb);
   if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
   /* Add the loop cleanup function.  */
   gsi = gsi_last_bb (exit_bb);
   if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
-    t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
+    t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
   else
   else
-    t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
+    t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
   stmt = gimple_build_call (t, 0);
   gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
   stmt = gimple_build_call (t, 0);
   gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
@@ -4058,9 +4128,14 @@ expand_omp_for_generic (struct omp_region *region,
        else
          n = (adj + N2 - N1) / STEP;
        q = n / nthreads;
        else
          n = (adj + N2 - N1) / STEP;
        q = n / nthreads;
-       q += (q * nthreads != n);
-       s0 = q * threadid;
-       e0 = min(s0 + q, n);
+       tt = n % nthreads;
+       if (threadid < tt) goto L3; else goto L4;
+    L3:
+       tt = 0;
+       q = q + 1;
+    L4:
+       s0 = q * threadid + tt;
+       e0 = s0 + q;
        V = s0 * STEP + N1;
        if (s0 >= e0) goto L2; else goto L0;
     L0:
        V = s0 * STEP + N1;
        if (s0 >= e0) goto L2; else goto L0;
     L0:
@@ -4076,12 +4151,14 @@ static void
 expand_omp_for_static_nochunk (struct omp_region *region,
                               struct omp_for_data *fd)
 {
 expand_omp_for_static_nochunk (struct omp_region *region,
                               struct omp_for_data *fd)
 {
-  tree n, q, s0, e0, e, t, nthreads, threadid;
+  tree n, q, s0, e0, e, t, tt, nthreads, threadid;
   tree type, itype, vmain, vback;
   tree type, itype, vmain, vback;
-  basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
+  basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
+  basic_block body_bb, cont_bb;
   basic_block fin_bb;
   gimple_stmt_iterator gsi;
   gimple stmt;
   basic_block fin_bb;
   gimple_stmt_iterator gsi;
   gimple stmt;
+  edge ep;
 
   itype = type = TREE_TYPE (fd->loop.v);
   if (POINTER_TYPE_P (type))
 
   itype = type = TREE_TYPE (fd->loop.v);
   if (POINTER_TYPE_P (type))
@@ -4102,12 +4179,12 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   gsi = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
 
   gsi = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
-  
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
@@ -4135,19 +4212,39 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   t = fold_convert (itype, t);
   n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   t = fold_convert (itype, t);
   n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
+  q = create_tmp_var (itype, "q");
   t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
   t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
-  q = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
+  t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
+  gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
 
 
-  t = fold_build2 (MULT_EXPR, itype, q, nthreads);
-  t = fold_build2 (NE_EXPR, itype, t, n);
-  t = fold_build2 (PLUS_EXPR, itype, q, t);
-  q = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
+  tt = create_tmp_var (itype, "tt");
+  t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
+  t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
+  gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
+
+  t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
+  stmt = gimple_build_cond_empty (t);
+  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+
+  second_bb = split_block (entry_bb, stmt)->dest;
+  gsi = gsi_last_bb (second_bb);
+  gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
+
+  gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
+                    GSI_SAME_STMT);
+  stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
+                                      build_int_cst (itype, 1));
+  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+
+  third_bb = split_block (second_bb, stmt)->dest;
+  gsi = gsi_last_bb (third_bb);
+  gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
 
   t = build2 (MULT_EXPR, itype, q, threadid);
 
   t = build2 (MULT_EXPR, itype, q, threadid);
+  t = build2 (PLUS_EXPR, itype, t, tt);
   s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   t = fold_build2 (PLUS_EXPR, itype, s0, q);
   s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   t = fold_build2 (PLUS_EXPR, itype, s0, q);
-  t = fold_build2 (MIN_EXPR, itype, t, n);
   e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   t = build2 (GE_EXPR, boolean_type_node, s0, e0);
   e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   t = build2 (GE_EXPR, boolean_type_node, s0, e0);
@@ -4162,20 +4259,18 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   t = fold_convert (itype, s0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
   t = fold_convert (itype, s0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
-                    fold_convert (sizetype, t));
+    t = fold_build_pointer_plus (fd->loop.n1, t);
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
                                false, GSI_CONTINUE_LINKING);
   stmt = gimple_build_assign (fd->loop.v, t);
   gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
                                false, GSI_CONTINUE_LINKING);
   stmt = gimple_build_assign (fd->loop.v, t);
   gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+
   t = fold_convert (itype, e0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
   t = fold_convert (itype, e0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
-                    fold_convert (sizetype, t));
+    t = fold_build_pointer_plus (fd->loop.n1, t);
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
@@ -4190,8 +4285,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   vback = gimple_omp_continue_control_def (stmt);
 
   if (POINTER_TYPE_P (type))
   vback = gimple_omp_continue_control_def (stmt);
 
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, vmain,
-                    fold_convert (sizetype, fd->loop.step));
+    t = fold_build_pointer_plus (vmain, fd->loop.step);
   else
     t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
   t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
   else
     t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
   t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
@@ -4213,13 +4307,20 @@ expand_omp_for_static_nochunk (struct omp_region *region,
   gsi_remove (&gsi, true);
 
   /* Connect all the blocks.  */
   gsi_remove (&gsi, true);
 
   /* Connect all the blocks.  */
-  find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
-  find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
+  ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
+  ep->probability = REG_BR_PROB_BASE / 4 * 3;
+  ep = find_edge (entry_bb, second_bb);
+  ep->flags = EDGE_TRUE_VALUE;
+  ep->probability = REG_BR_PROB_BASE / 4;
+  find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
+  find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
 
   find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
   find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
 
   find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
   find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
-  set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
+
+  set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
+  set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
+  set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
   set_immediate_dominator (CDI_DOMINATORS, body_bb,
                           recompute_dominator (CDI_DOMINATORS, body_bb));
   set_immediate_dominator (CDI_DOMINATORS, fin_bb,
   set_immediate_dominator (CDI_DOMINATORS, body_bb,
                           recompute_dominator (CDI_DOMINATORS, body_bb));
   set_immediate_dominator (CDI_DOMINATORS, fin_bb,
@@ -4300,12 +4401,12 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   si = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
 
   si = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
-  
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
@@ -4358,8 +4459,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
   t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
-                    fold_convert (sizetype, t));
+    t = fold_build_pointer_plus (fd->loop.n1, t);
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
@@ -4391,8 +4491,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   t = fold_convert (itype, s0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
   t = fold_convert (itype, s0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
-                    fold_convert (sizetype, t));
+    t = fold_build_pointer_plus (fd->loop.n1, t);
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   t = force_gimple_operand_gsi (&si, t, false, NULL_TREE,
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   t = force_gimple_operand_gsi (&si, t, false, NULL_TREE,
@@ -4403,8 +4502,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   t = fold_convert (itype, e0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
   t = fold_convert (itype, e0);
   t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
-                    fold_convert (sizetype, t));
+    t = fold_build_pointer_plus (fd->loop.n1, t);
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
   else
     t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
   e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
@@ -4419,8 +4517,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
   v_back = gimple_omp_continue_control_def (stmt);
 
   if (POINTER_TYPE_P (type))
   v_back = gimple_omp_continue_control_def (stmt);
 
   if (POINTER_TYPE_P (type))
-    t = fold_build2 (POINTER_PLUS_EXPR, type, v_main,
-                    fold_convert (sizetype, fd->loop.step));
+    t = fold_build_pointer_plus (v_main, fd->loop.step);
   else
     t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
   stmt = gimple_build_assign (v_back, t);
   else
     t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
   stmt = gimple_build_assign (v_back, t);
@@ -4428,7 +4525,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
 
   t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
   gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
 
   t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
   gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
-  
+
   /* Remove GIMPLE_OMP_CONTINUE.  */
   gsi_remove (&si, true);
 
   /* Remove GIMPLE_OMP_CONTINUE.  */
   gsi_remove (&si, true);
 
@@ -4478,6 +4575,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
           gsi_next (&psi), ++i)
        {
          gimple nphi;
           gsi_next (&psi), ++i)
        {
          gimple nphi;
+         source_location locus;
 
          phi = gsi_stmt (psi);
          t = gimple_phi_result (phi);
 
          phi = gsi_stmt (psi);
          t = gimple_phi_result (phi);
@@ -4486,12 +4584,15 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
          SSA_NAME_DEF_STMT (t) = nphi;
 
          t = PHI_ARG_DEF_FROM_EDGE (phi, se);
          SSA_NAME_DEF_STMT (t) = nphi;
 
          t = PHI_ARG_DEF_FROM_EDGE (phi, se);
+         locus = gimple_phi_arg_location_from_edge (phi, se);
+
          /* A special case -- fd->loop.v is not yet computed in
             iter_part_bb, we need to use v_extra instead.  */
          if (t == fd->loop.v)
            t = v_extra;
          /* A special case -- fd->loop.v is not yet computed in
             iter_part_bb, we need to use v_extra instead.  */
          if (t == fd->loop.v)
            t = v_extra;
-         add_phi_arg (nphi, t, ene);
-         add_phi_arg (nphi, redirect_edge_var_map_def (vm), re);
+         add_phi_arg (nphi, t, ene, locus);
+         locus = redirect_edge_var_map_location (vm);
+         add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
        }
       gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head));
       redirect_edge_var_map_clear (re);
        }
       gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head));
       redirect_edge_var_map_clear (re);
@@ -4506,8 +4607,10 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
       /* Make phi node for trip.  */
       phi = create_phi_node (trip_main, iter_part_bb);
       SSA_NAME_DEF_STMT (trip_main) = phi;
       /* Make phi node for trip.  */
       phi = create_phi_node (trip_main, iter_part_bb);
       SSA_NAME_DEF_STMT (trip_main) = phi;
-      add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
-      add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
+      add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
+                  UNKNOWN_LOCATION);
+      add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
+                  UNKNOWN_LOCATION);
     }
 
   set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
     }
 
   set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
@@ -4565,14 +4668,14 @@ expand_omp_for (struct omp_region *region)
       fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
                  ? 3 : fd.sched_kind;
       fn_index += fd.have_ordered * 4;
       fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
                  ? 3 : fd.sched_kind;
       fn_index += fd.have_ordered * 4;
-      start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
-      next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
+      start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
+      next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
       if (fd.iter_type == long_long_unsigned_type_node)
        {
       if (fd.iter_type == long_long_unsigned_type_node)
        {
-         start_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_START
-                     - BUILT_IN_GOMP_LOOP_STATIC_START;
-         next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
-                    - BUILT_IN_GOMP_LOOP_STATIC_NEXT;
+         start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
+                       - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
+         next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
+                     - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
        }
       expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
                              (enum built_in_function) next_ix);
        }
       expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
                              (enum built_in_function) next_ix);
@@ -4612,7 +4715,7 @@ expand_omp_for (struct omp_region *region)
 static void
 expand_omp_sections (struct omp_region *region)
 {
 static void
 expand_omp_sections (struct omp_region *region)
 {
-  tree t, u, vin = NULL, vmain, vnext, l1, l2;
+  tree t, u, vin = NULL, vmain, vnext, l2;
   VEC (tree,heap) *label_vec;
   unsigned len;
   basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
   VEC (tree,heap) *label_vec;
   unsigned len;
   basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
@@ -4631,7 +4734,7 @@ expand_omp_sections (struct omp_region *region)
   l2_bb = region->exit;
   if (exit_reachable)
     {
   l2_bb = region->exit;
   if (exit_reachable)
     {
-      if (single_pred (l2_bb) == l0_bb)
+      if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
        l2 = gimple_block_label (l2_bb);
       else
        {
        l2 = gimple_block_label (l2_bb);
       else
        {
@@ -4657,12 +4760,10 @@ expand_omp_sections (struct omp_region *region)
              }
        }
       default_bb = create_empty_bb (l1_bb->prev_bb);
              }
        }
       default_bb = create_empty_bb (l1_bb->prev_bb);
-      l1 = gimple_block_label (l1_bb);
     }
   else
     {
       default_bb = create_empty_bb (l0_bb);
     }
   else
     {
       default_bb = create_empty_bb (l0_bb);
-      l1 = NULL_TREE;
       l2 = gimple_block_label (default_bb);
     }
 
       l2 = gimple_block_label (default_bb);
     }
 
@@ -4687,13 +4788,13 @@ expand_omp_sections (struct omp_region *region)
         call GOMP_sections_start.  */
       t = build_int_cst (unsigned_type_node,
                         exit_reachable ? len - 1 : len);
         call GOMP_sections_start.  */
       t = build_int_cst (unsigned_type_node,
                         exit_reachable ? len - 1 : len);
-      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
+      u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
       stmt = gimple_build_call (u, 1, t);
     }
   else
     {
       /* Otherwise, call GOMP_sections_next.  */
       stmt = gimple_build_call (u, 1, t);
     }
   else
     {
       /* Otherwise, call GOMP_sections_next.  */
-      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
+      u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
       stmt = gimple_build_call (u, 0);
     }
   gimple_call_set_lhs (stmt, vin);
       stmt = gimple_build_call (u, 0);
     }
   gimple_call_set_lhs (stmt, vin);
@@ -4720,8 +4821,7 @@ expand_omp_sections (struct omp_region *region)
   i = 0;
   if (exit_reachable)
     {
   i = 0;
   if (exit_reachable)
     {
-      t = build3 (CASE_LABEL_EXPR, void_type_node,
-                 build_int_cst (unsigned_type_node, 0), NULL, l2);
+      t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
       VEC_quick_push (tree, label_vec, t);
       i++;
     }
       VEC_quick_push (tree, label_vec, t);
       i++;
     }
@@ -4746,7 +4846,7 @@ expand_omp_sections (struct omp_region *region)
 
       t = gimple_block_label (s_entry_bb);
       u = build_int_cst (unsigned_type_node, casei);
 
       t = gimple_block_label (s_entry_bb);
       u = build_int_cst (unsigned_type_node, casei);
-      u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
+      u = build_case_label (u, NULL, t);
       VEC_quick_push (tree, label_vec, u);
 
       si = gsi_last_bb (s_entry_bb);
       VEC_quick_push (tree, label_vec, u);
 
       si = gsi_last_bb (s_entry_bb);
@@ -4767,7 +4867,7 @@ expand_omp_sections (struct omp_region *region)
 
   /* Error handling code goes in DEFAULT_BB.  */
   t = gimple_block_label (default_bb);
 
   /* Error handling code goes in DEFAULT_BB.  */
   t = gimple_block_label (default_bb);
-  u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
+  u = build_case_label (NULL, NULL, t);
   make_edge (l0_bb, default_bb, 0);
 
   stmt = gimple_build_switch_vec (vmain, u, label_vec);
   make_edge (l0_bb, default_bb, 0);
 
   stmt = gimple_build_switch_vec (vmain, u, label_vec);
@@ -4776,16 +4876,19 @@ expand_omp_sections (struct omp_region *region)
   VEC_free (tree, heap, label_vec);
 
   si = gsi_start_bb (default_bb);
   VEC_free (tree, heap, label_vec);
 
   si = gsi_start_bb (default_bb);
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
+  stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
   gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
 
   if (exit_reachable)
     {
   gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
 
   if (exit_reachable)
     {
+      tree bfn_decl;
+
       /* Code to get the next section goes in L1_BB.  */
       si = gsi_last_bb (l1_bb);
       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
 
       /* Code to get the next section goes in L1_BB.  */
       si = gsi_last_bb (l1_bb);
       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
 
-      stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
+      bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
+      stmt = gimple_build_call (bfn_decl, 0);
       gimple_call_set_lhs (stmt, vnext);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
       gimple_call_set_lhs (stmt, vnext);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
@@ -4795,9 +4898,9 @@ expand_omp_sections (struct omp_region *region)
       /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
       si = gsi_last_bb (l2_bb);
       if (gimple_omp_return_nowait_p (gsi_stmt (si)))
       /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
       si = gsi_last_bb (l2_bb);
       if (gimple_omp_return_nowait_p (gsi_stmt (si)))
-       t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
+       t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
       else
       else
-       t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
+       t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
       stmt = gimple_build_call (t, 0);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
       stmt = gimple_build_call (t, 0);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
@@ -4871,7 +4974,132 @@ expand_omp_synch (struct omp_region *region)
 }
 
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
 }
 
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
-   operation as a __sync_fetch_and_op builtin.  INDEX is log2 of the
+   operation as a normal volatile load.  */
+
+static bool
+expand_omp_atomic_load (basic_block load_bb, tree addr,
+                       tree loaded_val, int index)
+{
+  enum built_in_function tmpbase;
+  gimple_stmt_iterator gsi;
+  basic_block store_bb;
+  location_t loc;
+  gimple stmt;
+  tree decl, call, type, itype;
+
+  gsi = gsi_last_bb (load_bb);
+  stmt = gsi_stmt (gsi);
+  gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
+  loc = gimple_location (stmt);
+
+  /* ??? If the target does not implement atomic_load_optab[mode], and mode
+     is smaller than word size, then expand_atomic_load assumes that the load
+     is atomic.  We could avoid the builtin entirely in this case.  */
+
+  tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
+  decl = builtin_decl_explicit (tmpbase);
+  if (decl == NULL_TREE)
+    return false;
+
+  type = TREE_TYPE (loaded_val);
+  itype = TREE_TYPE (TREE_TYPE (decl));
+
+  call = build_call_expr_loc (loc, decl, 2, addr,
+                             build_int_cst (NULL, MEMMODEL_RELAXED));
+  if (!useless_type_conversion_p (type, itype))
+    call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
+  call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
+
+  force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
+  gsi_remove (&gsi, true);
+
+  store_bb = single_succ (load_bb);
+  gsi = gsi_last_bb (store_bb);
+  gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
+  gsi_remove (&gsi, true);
+
+  if (gimple_in_ssa_p (cfun))
+    update_ssa (TODO_update_ssa_no_phi);
+
+  return true;
+}
+
+/* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
+   operation as a normal volatile store.  */
+
+static bool
+expand_omp_atomic_store (basic_block load_bb, tree addr,
+                        tree loaded_val, tree stored_val, int index)
+{
+  enum built_in_function tmpbase;
+  gimple_stmt_iterator gsi;
+  basic_block store_bb = single_succ (load_bb);
+  location_t loc;
+  gimple stmt;
+  tree decl, call, type, itype;
+  enum machine_mode imode;
+  bool exchange;
+
+  gsi = gsi_last_bb (load_bb);
+  stmt = gsi_stmt (gsi);
+  gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
+
+  /* If the load value is needed, then this isn't a store but an exchange.  */
+  exchange = gimple_omp_atomic_need_value_p (stmt);
+
+  gsi = gsi_last_bb (store_bb);
+  stmt = gsi_stmt (gsi);
+  gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
+  loc = gimple_location (stmt);
+
+  /* ??? If the target does not implement atomic_store_optab[mode], and mode
+     is smaller than word size, then expand_atomic_store assumes that the store
+     is atomic.  We could avoid the builtin entirely in this case.  */
+
+  tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
+  tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
+  decl = builtin_decl_explicit (tmpbase);
+  if (decl == NULL_TREE)
+    return false;
+
+  type = TREE_TYPE (stored_val);
+
+  /* Dig out the type of the function's second argument.  */
+  itype = TREE_TYPE (decl);
+  itype = TYPE_ARG_TYPES (itype);
+  itype = TREE_CHAIN (itype);
+  itype = TREE_VALUE (itype);
+  imode = TYPE_MODE (itype);
+
+  if (exchange && !can_atomic_exchange_p (imode, true))
+    return false;
+
+  if (!useless_type_conversion_p (itype, type))
+    stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
+  call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
+                             build_int_cst (NULL, MEMMODEL_RELAXED));
+  if (exchange)
+    {
+      if (!useless_type_conversion_p (type, itype))
+       call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
+      call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
+    }
+
+  force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
+  gsi_remove (&gsi, true);
+
+  /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above.  */
+  gsi = gsi_last_bb (load_bb);
+  gsi_remove (&gsi, true);
+
+  if (gimple_in_ssa_p (cfun))
+    update_ssa (TODO_update_ssa_no_phi);
+
+  return true;
+}
+
+/* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
+   operation as a __atomic_fetch_op builtin.  INDEX is log2 of the
    size of the data type, and thus usable to find the index of the builtin
    decl.  Returns false if the expression is not of the proper form.  */
 
    size of the data type, and thus usable to find the index of the builtin
    decl.  Returns false if the expression is not of the proper form.  */
 
@@ -4880,66 +5108,75 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
                            tree addr, tree loaded_val,
                            tree stored_val, int index)
 {
                            tree addr, tree loaded_val,
                            tree stored_val, int index)
 {
-  enum built_in_function base;
+  enum built_in_function oldbase, newbase, tmpbase;
   tree decl, itype, call;
   tree decl, itype, call;
-  enum insn_code *optab;
-  tree rhs;
+  tree lhs, rhs;
   basic_block store_bb = single_succ (load_bb);
   gimple_stmt_iterator gsi;
   gimple stmt;
   basic_block store_bb = single_succ (load_bb);
   gimple_stmt_iterator gsi;
   gimple stmt;
+  location_t loc;
+  enum tree_code code;
+  bool need_old, need_new;
+  enum machine_mode imode;
 
   /* We expect to find the following sequences:
 
   /* We expect to find the following sequences:
-   
+
    load_bb:
        GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
 
    store_bb:
        val = tmp OP something; (or: something OP tmp)
    load_bb:
        GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
 
    store_bb:
        val = tmp OP something; (or: something OP tmp)
-       GIMPLE_OMP_STORE (val) 
+       GIMPLE_OMP_STORE (val)
 
 
-  ???FIXME: Allow a more flexible sequence.  
+  ???FIXME: Allow a more flexible sequence.
   Perhaps use data flow to pick the statements.
   Perhaps use data flow to pick the statements.
-  
+
   */
 
   gsi = gsi_after_labels (store_bb);
   stmt = gsi_stmt (gsi);
   */
 
   gsi = gsi_after_labels (store_bb);
   stmt = gsi_stmt (gsi);
+  loc = gimple_location (stmt);
   if (!is_gimple_assign (stmt))
     return false;
   gsi_next (&gsi);
   if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
     return false;
   if (!is_gimple_assign (stmt))
     return false;
   gsi_next (&gsi);
   if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
     return false;
+  need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
+  need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
+  gcc_checking_assert (!need_old || !need_new);
 
   if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
     return false;
 
   /* Check for one of the supported fetch-op operations.  */
 
   if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
     return false;
 
   /* Check for one of the supported fetch-op operations.  */
-  switch (gimple_assign_rhs_code (stmt))
+  code = gimple_assign_rhs_code (stmt);
+  switch (code)
     {
     case PLUS_EXPR:
     case POINTER_PLUS_EXPR:
     {
     case PLUS_EXPR:
     case POINTER_PLUS_EXPR:
-      base = BUILT_IN_FETCH_AND_ADD_N;
-      optab = sync_add_optab;
+      oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
+      newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
       break;
     case MINUS_EXPR:
       break;
     case MINUS_EXPR:
-      base = BUILT_IN_FETCH_AND_SUB_N;
-      optab = sync_add_optab;
+      oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
+      newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
       break;
     case BIT_AND_EXPR:
       break;
     case BIT_AND_EXPR:
-      base = BUILT_IN_FETCH_AND_AND_N;
-      optab = sync_and_optab;
+      oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
+      newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
       break;
     case BIT_IOR_EXPR:
       break;
     case BIT_IOR_EXPR:
-      base = BUILT_IN_FETCH_AND_OR_N;
-      optab = sync_ior_optab;
+      oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
+      newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
       break;
     case BIT_XOR_EXPR:
       break;
     case BIT_XOR_EXPR:
-      base = BUILT_IN_FETCH_AND_XOR_N;
-      optab = sync_xor_optab;
+      oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
+      newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
       break;
     default:
       return false;
     }
       break;
     default:
       return false;
     }
+
   /* Make sure the expression is of the proper form.  */
   if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
     rhs = gimple_assign_rhs2 (stmt);
   /* Make sure the expression is of the proper form.  */
   if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
     rhs = gimple_assign_rhs2 (stmt);
@@ -4949,16 +5186,39 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
   else
     return false;
 
   else
     return false;
 
-  decl = built_in_decls[base + index + 1];
+  tmpbase = ((enum built_in_function)
+            ((need_new ? newbase : oldbase) + index + 1));
+  decl = builtin_decl_explicit (tmpbase);
+  if (decl == NULL_TREE)
+    return false;
   itype = TREE_TYPE (TREE_TYPE (decl));
   itype = TREE_TYPE (TREE_TYPE (decl));
+  imode = TYPE_MODE (itype);
 
 
-  if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing)
+  /* We could test all of the various optabs involved, but the fact of the
+     matter is that (with the exception of i486 vs i586 and xadd) all targets
+     that support any atomic operaton optab also implements compare-and-swap.
+     Let optabs.c take care of expanding any compare-and-swap loop.  */
+  if (!can_compare_and_swap_p (imode, true))
     return false;
 
   gsi = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
     return false;
 
   gsi = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
-  call = build_call_expr (decl, 2, addr, fold_convert (itype, rhs));
-  call = fold_convert (void_type_node, call);
+
+  /* OpenMP does not imply any barrier-like semantics on its atomic ops.
+     It only requires that the operation happen atomically.  Thus we can
+     use the RELAXED memory model.  */
+  call = build_call_expr_loc (loc, decl, 3, addr,
+                             fold_convert_loc (loc, itype, rhs),
+                             build_int_cst (NULL, MEMMODEL_RELAXED));
+
+  if (need_old || need_new)
+    {
+      lhs = need_old ? loaded_val : stored_val;
+      call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
+      call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
+    }
+  else
+    call = fold_convert_loc (loc, void_type_node, call);
   force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
 
   force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
 
@@ -4997,12 +5257,19 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
   basic_block loop_header = single_succ (load_bb);
   gimple phi, stmt;
   edge e;
   basic_block loop_header = single_succ (load_bb);
   gimple phi, stmt;
   edge e;
-
-  cmpxchg = built_in_decls[BUILT_IN_VAL_COMPARE_AND_SWAP_N + index + 1];
+  enum built_in_function fncode;
+
+  /* ??? We need a non-pointer interface to __atomic_compare_exchange in
+     order to use the RELAXED memory model effectively.  */
+  fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+                                   + index + 1);
+  cmpxchg = builtin_decl_explicit (fncode);
+  if (cmpxchg == NULL_TREE)
+    return false;
   type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   itype = TREE_TYPE (TREE_TYPE (cmpxchg));
 
   type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   itype = TREE_TYPE (TREE_TYPE (cmpxchg));
 
-  if (sync_compare_and_swap[TYPE_MODE (itype)] == CODE_FOR_nothing)
+  if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
     return false;
 
   /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD.  */
     return false;
 
   /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD.  */
@@ -5016,14 +5283,14 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
     {
       tree iaddr_val;
 
     {
       tree iaddr_val;
 
-      iaddr = create_tmp_var (build_pointer_type (itype), NULL);
+      iaddr = create_tmp_var (build_pointer_type_for_mode (itype, ptr_mode,
+                                                          true), NULL);
       iaddr_val
        = force_gimple_operand_gsi (&si,
                                    fold_convert (TREE_TYPE (iaddr), addr),
                                    false, NULL_TREE, true, GSI_SAME_STMT);
       stmt = gimple_build_assign (iaddr, iaddr_val);
       gsi_insert_before (&si, stmt, GSI_SAME_STMT);
       iaddr_val
        = force_gimple_operand_gsi (&si,
                                    fold_convert (TREE_TYPE (iaddr), addr),
                                    false, NULL_TREE, true, GSI_SAME_STMT);
       stmt = gimple_build_assign (iaddr, iaddr_val);
       gsi_insert_before (&si, stmt, GSI_SAME_STMT);
-      DECL_POINTER_ALIAS_SET (iaddr) = 0;
       loadedi = create_tmp_var (itype, NULL);
       if (gimple_in_ssa_p (cfun))
        {
       loadedi = create_tmp_var (itype, NULL);
       if (gimple_in_ssa_p (cfun))
        {
@@ -5038,8 +5305,12 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
       loadedi = loaded_val;
     }
 
       loadedi = loaded_val;
     }
 
-  initial = force_gimple_operand_gsi (&si, build_fold_indirect_ref (iaddr),
-                                     true, NULL_TREE, true, GSI_SAME_STMT);
+  initial
+    = force_gimple_operand_gsi (&si,
+                               build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
+                                       iaddr,
+                                       build_int_cst (TREE_TYPE (iaddr), 0)),
+                               true, NULL_TREE, true, GSI_SAME_STMT);
 
   /* Move the value to the LOADEDI temporary.  */
   if (gimple_in_ssa_p (cfun))
 
   /* Move the value to the LOADEDI temporary.  */
   if (gimple_in_ssa_p (cfun))
@@ -5113,7 +5384,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
     }
 
   /* Note that we always perform the comparison as an integer, even for
     }
 
   /* Note that we always perform the comparison as an integer, even for
-     floating point.  This allows the atomic operation to properly 
+     floating point.  This allows the atomic operation to properly
      succeed even with NaNs and -0.0.  */
   stmt = gimple_build_cond_empty
            (build2 (NE_EXPR, boolean_type_node,
      succeed even with NaNs and -0.0.  */
   stmt = gimple_build_cond_empty
            (build2 (NE_EXPR, boolean_type_node,
@@ -5154,18 +5425,18 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
    references are within #pragma omp atomic directives.  According to
    responses received from omp@openmp.org, appears to be within spec.
    Which makes sense, since that's how several other compilers handle
    references are within #pragma omp atomic directives.  According to
    responses received from omp@openmp.org, appears to be within spec.
    Which makes sense, since that's how several other compilers handle
-   this situation as well.  
+   this situation as well.
    LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
    expanding.  STORED_VAL is the operand of the matching
    GIMPLE_OMP_ATOMIC_STORE.
 
    LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
    expanding.  STORED_VAL is the operand of the matching
    GIMPLE_OMP_ATOMIC_STORE.
 
-   We replace 
-   GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with  
+   We replace
+   GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
    loaded_val = *addr;
 
    and replace
    loaded_val = *addr;
 
    and replace
-   GIMPLE_OMP_ATOMIC_ATORE (stored_val)  with
-   *addr = stored_val;  
+   GIMPLE_OMP_ATOMIC_STORE (stored_val)  with
+   *addr = stored_val;
 */
 
 static bool
 */
 
 static bool
@@ -5179,23 +5450,23 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
   si = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
 
   si = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
 
-  t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
-  t = build_function_call_expr (t, 0);
+  t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+  t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
-  stmt = gimple_build_assign (loaded_val, build_fold_indirect_ref (addr));
+  stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
   si = gsi_last_bb (store_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
 
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
   si = gsi_last_bb (store_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
 
-  stmt = gimple_build_assign (build_fold_indirect_ref (unshare_expr (addr)),
-                               stored_val);
+  stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
+                             stored_val);
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
 
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
 
-  t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
-  t = build_function_call_expr (t, 0);
+  t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+  t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
@@ -5204,12 +5475,12 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
   return true;
 }
 
   return true;
 }
 
-/* Expand an GIMPLE_OMP_ATOMIC statement.  We try to expand 
-   using expand_omp_atomic_fetch_op. If it failed, we try to 
+/* Expand an GIMPLE_OMP_ATOMIC statement.  We try to expand
+   using expand_omp_atomic_fetch_op. If it failed, we try to
    call expand_omp_atomic_pipeline, and if it fails too, the
    ultimate fallback is wrapping the operation in a mutex
    call expand_omp_atomic_pipeline, and if it fails too, the
    ultimate fallback is wrapping the operation in a mutex
-   (expand_omp_atomic_mutex).  REGION is the atomic region built 
-   by build_omp_regions_1().  */ 
+   (expand_omp_atomic_mutex).  REGION is the atomic region built
+   by build_omp_regions_1().  */
 
 static void
 expand_omp_atomic (struct omp_region *region)
 
 static void
 expand_omp_atomic (struct omp_region *region)
@@ -5230,16 +5501,34 @@ expand_omp_atomic (struct omp_region *region)
       unsigned int align = TYPE_ALIGN_UNIT (type);
 
       /* __sync builtins require strict data alignment.  */
       unsigned int align = TYPE_ALIGN_UNIT (type);
 
       /* __sync builtins require strict data alignment.  */
-      if (exact_log2 (align) >= index)
+      /* ??? Assume BIGGEST_ALIGNMENT *is* aligned.  */
+      if (exact_log2 (align) >= index
+         || align * BITS_PER_UNIT >= BIGGEST_ALIGNMENT)
        {
        {
+         /* Atomic load.  */
+         if (loaded_val == stored_val
+             && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
+                 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
+             && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
+             && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
+           return;
+
+         /* Atomic store.  */
+         if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
+              || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
+             && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
+             && store_bb == single_succ (load_bb)
+             && first_stmt (store_bb) == store
+             && expand_omp_atomic_store (load_bb, addr, loaded_val,
+                                         stored_val, index))
+           return;
+
          /* When possible, use specialized atomic update functions.  */
          if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
          /* When possible, use specialized atomic update functions.  */
          if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
-             && store_bb == single_succ (load_bb))
-           {
-             if (expand_omp_atomic_fetch_op (load_bb, addr,
-                                             loaded_val, stored_val, index))
-               return;
-           }
+             && store_bb == single_succ (load_bb)
+             && expand_omp_atomic_fetch_op (load_bb, addr,
+                                            loaded_val, stored_val, index))
+           return;
 
          /* If we don't have specialized __sync builtins, try and implement
             as a compare and swap loop.  */
 
          /* If we don't have specialized __sync builtins, try and implement
             as a compare and swap loop.  */
@@ -5469,10 +5758,10 @@ execute_expand_omp (void)
 static bool
 gate_expand_omp (void)
 {
 static bool
 gate_expand_omp (void)
 {
-  return (flag_openmp != 0 && errorcount == 0);
+  return (flag_openmp != 0 && !seen_error ());
 }
 
 }
 
-struct gimple_opt_pass pass_expand_omp = 
+struct gimple_opt_pass pass_expand_omp =
 {
  {
   GIMPLE_PASS,
 {
  {
   GIMPLE_PASS,
@@ -5487,7 +5776,7 @@ struct gimple_opt_pass pass_expand_omp =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
+  0                                    /* todo_flags_finish */
  }
 };
 \f
  }
 };
 \f
@@ -5544,7 +5833,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
          gimple_seq_add_seq (&body, l);
          gimple_omp_section_set_last (sec_start);
        }
          gimple_seq_add_seq (&body, l);
          gimple_omp_section_set_last (sec_start);
        }
-      
+
       gimple_seq_add_stmt (&body, gimple_build_omp_return (false));
     }
 
       gimple_seq_add_stmt (&body, gimple_build_omp_return (false));
     }
 
@@ -5611,14 +5900,15 @@ lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
   gimple call, cond;
   tree lhs, decl;
 
   gimple call, cond;
   tree lhs, decl;
 
-  decl = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
+  decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
   lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
   call = gimple_build_call (decl, 0);
   gimple_call_set_lhs (call, lhs);
   gimple_seq_add_stmt (pre_p, call);
 
   cond = gimple_build_cond (EQ_EXPR, lhs,
   lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
   call = gimple_build_call (decl, 0);
   gimple_call_set_lhs (call, lhs);
   gimple_seq_add_stmt (pre_p, call);
 
   cond = gimple_build_cond (EQ_EXPR, lhs,
-                           fold_convert (TREE_TYPE (lhs), boolean_true_node),
+                           fold_convert_loc (loc, TREE_TYPE (lhs),
+                                             boolean_true_node),
                            tlabel, flabel);
   gimple_seq_add_stmt (pre_p, cond);
   gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
                            tlabel, flabel);
   gimple_seq_add_stmt (pre_p, cond);
   gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
@@ -5659,7 +5949,7 @@ lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
 static void
 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
 {
 static void
 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
 {
-  tree ptr_type, t, l0, l1, l2;
+  tree ptr_type, t, l0, l1, l2, bfn_decl;
   gimple_seq copyin_seq;
   location_t loc = gimple_location (single_stmt);
 
   gimple_seq copyin_seq;
   location_t loc = gimple_location (single_stmt);
 
@@ -5672,8 +5962,9 @@ lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
   l1 = create_artificial_label (loc);
   l2 = create_artificial_label (loc);
 
   l1 = create_artificial_label (loc);
   l2 = create_artificial_label (loc);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
-  t = fold_convert (ptr_type, t);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
+  t = build_call_expr_loc (loc, bfn_decl, 0);
+  t = fold_convert_loc (loc, ptr_type, t);
   gimplify_assign (ctx->receiver_decl, t, pre_p);
 
   t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
   gimplify_assign (ctx->receiver_decl, t, pre_p);
 
   t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
@@ -5690,8 +5981,9 @@ lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
   lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
                              &copyin_seq, ctx);
 
   lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
                              &copyin_seq, ctx);
 
-  t = build_fold_addr_expr (ctx->sender_decl);
-  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
+  t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
+  t = build_call_expr_loc (loc, bfn_decl, 1, t);
   gimplify_and_add (t, pre_p);
 
   t = build_and_jump (&l2);
   gimplify_and_add (t, pre_p);
 
   t = build_and_jump (&l2);
@@ -5735,7 +6027,7 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   bind_body = maybe_catch_exception (bind_body);
 
 
   bind_body = maybe_catch_exception (bind_body);
 
-  t = gimple_build_omp_return 
+  t = gimple_build_omp_return
         (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
                            OMP_CLAUSE_NOWAIT));
   gimple_seq_add_stmt (&bind_body, t);
         (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
                            OMP_CLAUSE_NOWAIT));
   gimple_seq_add_stmt (&bind_body, t);
@@ -5758,8 +6050,9 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 static void
 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
 static void
 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
-  tree block, lab = NULL, x;
+  tree block, lab = NULL, x, bfn_decl;
   gimple stmt = gsi_stmt (*gsi_p), bind;
   gimple stmt = gsi_stmt (*gsi_p), bind;
+  location_t loc = gimple_location (stmt);
   gimple_seq tseq;
   struct gimplify_ctx gctx;
 
   gimple_seq tseq;
   struct gimplify_ctx gctx;
 
@@ -5769,7 +6062,8 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
                                 block);
 
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
                                 block);
 
-  x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+  x = build_call_expr_loc (loc, bfn_decl, 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));
   tseq = NULL;
   x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
   x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
   tseq = NULL;
@@ -5808,7 +6102,8 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
                                   block);
 
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
                                   block);
 
-  x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
+  x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
+                        0);
   gimple_bind_add_stmt (bind, x);
 
   lower_omp (gimple_omp_body (stmt), ctx);
   gimple_bind_add_stmt (bind, x);
 
   lower_omp (gimple_omp_body (stmt), ctx);
@@ -5816,7 +6111,7 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
 
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
 
-  x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
+  x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
   gimple_bind_add_stmt (bind, x);
 
   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
   gimple_bind_add_stmt (bind, x);
 
   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
@@ -5843,6 +6138,7 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   tree block;
   tree name, lock, unlock;
   gimple stmt = gsi_stmt (*gsi_p), bind;
   tree block;
   tree name, lock, unlock;
   gimple stmt = gsi_stmt (*gsi_p), bind;
+  location_t loc = gimple_location (stmt);
   gimple_seq tbody;
   struct gimplify_ctx gctx;
 
   gimple_seq tbody;
   struct gimplify_ctx gctx;
 
@@ -5854,7 +6150,9 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
       if (!critical_name_mutexes)
        critical_name_mutexes
 
       if (!critical_name_mutexes)
        critical_name_mutexes
-         = splay_tree_new_ggc (splay_tree_compare_pointers);
+         = splay_tree_new_ggc (splay_tree_compare_pointers,
+                               ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
+                               ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
 
       n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
       if (n == NULL)
 
       n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
       if (n == NULL)
@@ -5879,19 +6177,20 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       else
        decl = (tree) n->value;
 
       else
        decl = (tree) n->value;
 
-      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
-      lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
+      lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
+      lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
 
 
-      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
-      unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
+      unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
+      unlock = build_call_expr_loc (loc, unlock, 1,
+                               build_fold_addr_expr_loc (loc, decl));
     }
   else
     {
     }
   else
     {
-      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
-      lock = build_call_expr (lock, 0);
+      lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
+      lock = build_call_expr_loc (loc, lock, 0);
 
 
-      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
-      unlock = build_call_expr (unlock, 0);
+      unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
+      unlock = build_call_expr_loc (loc, unlock, 0);
     }
 
   push_gimplify_context (&gctx);
     }
 
   push_gimplify_context (&gctx);
@@ -5934,7 +6233,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
   tree clauses, cond, vinit;
   enum tree_code cond_code;
   gimple_seq stmts;
   tree clauses, cond, vinit;
   enum tree_code cond_code;
   gimple_seq stmts;
-  
+
   cond_code = fd->loop.cond_code;
   cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
 
   cond_code = fd->loop.cond_code;
   cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
 
@@ -5979,7 +6278,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   tree *rhs_p, block;
   struct omp_for_data fd;
   gimple stmt = gsi_stmt (*gsi_p), new_stmt;
   tree *rhs_p, block;
   struct omp_for_data fd;
   gimple stmt = gsi_stmt (*gsi_p), new_stmt;
-  gimple_seq omp_for_body, body, dlist, ilist;
+  gimple_seq omp_for_body, body, dlist;
   size_t i;
   struct gimplify_ctx gctx;
 
   size_t i;
   struct gimplify_ctx gctx;
 
@@ -6002,7 +6301,6 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
     }
 
   /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR.  */
     }
 
   /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR.  */
-  ilist = NULL;
   dlist = NULL;
   body = NULL;
   lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
   dlist = NULL;
   body = NULL;
   lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
@@ -6063,7 +6361,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gsi_replace (gsi_p, new_stmt, true);
 }
 
   gsi_replace (gsi_p, new_stmt, true);
 }
 
-/* Callback for walk_stmts.  Check if the current statement only contains 
+/* Callback for walk_stmts.  Check if the current statement only contains
    GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL.  */
 
 static tree
    GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL.  */
 
 static tree
@@ -6152,15 +6450,15 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
   splay_tree_node n;
   struct omp_taskcopy_context tcctx;
   struct gimplify_ctx gctx;
   splay_tree_node n;
   struct omp_taskcopy_context tcctx;
   struct gimplify_ctx gctx;
+  location_t loc = gimple_location (task_stmt);
 
   child_fn = gimple_omp_task_copy_fn (task_stmt);
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
   gcc_assert (child_cfun->cfg == NULL);
 
   child_fn = gimple_omp_task_copy_fn (task_stmt);
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
   gcc_assert (child_cfun->cfg == NULL);
-  child_cfun->dont_save_pending_sizes_p = 1;
   DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
 
   /* Reset DECL_CONTEXT on function arguments.  */
   DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
 
   /* Reset DECL_CONTEXT on function arguments.  */
-  for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
+  for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
     DECL_CONTEXT (t) = child_fn;
 
   /* Populate the function.  */
     DECL_CONTEXT (t) = child_fn;
 
   /* Populate the function.  */
@@ -6176,13 +6474,13 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
   /* Remap src and dst argument types if needed.  */
   record_type = ctx->record_type;
   srecord_type = ctx->srecord_type;
   /* Remap src and dst argument types if needed.  */
   record_type = ctx->record_type;
   srecord_type = ctx->srecord_type;
-  for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
+  for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
       {
        record_needs_remap = true;
        break;
       }
     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
       {
        record_needs_remap = true;
        break;
       }
-  for (f = TYPE_FIELDS (srecord_type); f ; f = TREE_CHAIN (f))
+  for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
       {
        srecord_needs_remap = true;
     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
       {
        srecord_needs_remap = true;
@@ -6194,11 +6492,12 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
       memset (&tcctx, '\0', sizeof (tcctx));
       tcctx.cb.src_fn = ctx->cb.src_fn;
       tcctx.cb.dst_fn = child_fn;
       memset (&tcctx, '\0', sizeof (tcctx));
       tcctx.cb.src_fn = ctx->cb.src_fn;
       tcctx.cb.dst_fn = child_fn;
-      tcctx.cb.src_node = cgraph_node (tcctx.cb.src_fn);
+      tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
+      gcc_checking_assert (tcctx.cb.src_node);
       tcctx.cb.dst_node = tcctx.cb.src_node;
       tcctx.cb.src_cfun = ctx->cb.src_cfun;
       tcctx.cb.copy_decl = task_copyfn_copy_decl;
       tcctx.cb.dst_node = tcctx.cb.src_node;
       tcctx.cb.src_cfun = ctx->cb.src_cfun;
       tcctx.cb.copy_decl = task_copyfn_copy_decl;
-      tcctx.cb.eh_region = -1;
+      tcctx.cb.eh_lp_nr = 0;
       tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
       tcctx.cb.decl_map = pointer_map_create ();
       tcctx.ctx = ctx;
       tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
       tcctx.cb.decl_map = pointer_map_create ();
       tcctx.ctx = ctx;
@@ -6215,7 +6514,7 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
 
   arg = DECL_ARGUMENTS (child_fn);
   TREE_TYPE (arg) = build_pointer_type (record_type);
 
   arg = DECL_ARGUMENTS (child_fn);
   TREE_TYPE (arg) = build_pointer_type (record_type);
-  sarg = TREE_CHAIN (arg);
+  sarg = DECL_CHAIN (arg);
   TREE_TYPE (sarg) = build_pointer_type (srecord_type);
 
   /* First pass: initialize temporaries used in record_type and srecord_type
   TREE_TYPE (sarg) = build_pointer_type (srecord_type);
 
   /* First pass: initialize temporaries used in record_type and srecord_type
@@ -6233,7 +6532,7 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
          n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
          sf = (tree) n->value;
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
          n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
          sf = (tree) n->value;
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
-         src = build_fold_indirect_ref (sarg);
+         src = build_simple_mem_ref_loc (loc, sarg);
          src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
          t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
          append_to_statement_list (t, &list);
          src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
          t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
          append_to_statement_list (t, &list);
@@ -6256,9 +6555,9 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
        sf = (tree) n->value;
        if (tcctx.cb.decl_map)
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
        sf = (tree) n->value;
        if (tcctx.cb.decl_map)
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
-       src = build_fold_indirect_ref (sarg);
+       src = build_simple_mem_ref_loc (loc, sarg);
        src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
        src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
-       dst = build_fold_indirect_ref (arg);
+       dst = build_simple_mem_ref_loc (loc, arg);
        dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
        t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
        append_to_statement_list (t, &list);
        dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
        t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
        append_to_statement_list (t, &list);
@@ -6279,14 +6578,14 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
            sf = (tree) n->value;
            if (tcctx.cb.decl_map)
              sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
            sf = (tree) n->value;
            if (tcctx.cb.decl_map)
              sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
-           src = build_fold_indirect_ref (sarg);
+           src = build_simple_mem_ref_loc (loc, sarg);
            src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
            if (use_pointer_for_field (decl, NULL) || is_reference (decl))
            src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
            if (use_pointer_for_field (decl, NULL) || is_reference (decl))
-             src = build_fold_indirect_ref (src);
+             src = build_simple_mem_ref_loc (loc, src);
          }
        else
          src = decl;
          }
        else
          src = decl;
-       dst = build_fold_indirect_ref (arg);
+       dst = build_simple_mem_ref_loc (loc, arg);
        dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
        t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
        append_to_statement_list (t, &list);
        dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
        t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
        append_to_statement_list (t, &list);
@@ -6305,14 +6604,14 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
            sf = (tree) n->value;
            if (tcctx.cb.decl_map)
              sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
            sf = (tree) n->value;
            if (tcctx.cb.decl_map)
              sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
-           src = build_fold_indirect_ref (sarg);
+           src = build_simple_mem_ref_loc (loc, sarg);
            src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
            if (use_pointer_for_field (decl, NULL))
            src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
            if (use_pointer_for_field (decl, NULL))
-             src = build_fold_indirect_ref (src);
+             src = build_simple_mem_ref_loc (loc, src);
          }
        else
          src = decl;
          }
        else
          src = decl;
-       dst = build_fold_indirect_ref (arg);
+       dst = build_simple_mem_ref_loc (loc, arg);
        dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
        t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
        append_to_statement_list (t, &list);
        dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
        t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
        append_to_statement_list (t, &list);
@@ -6344,10 +6643,10 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
                                 (splay_tree_key) TREE_OPERAND (ind, 0));
          sf = (tree) n->value;
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
                                 (splay_tree_key) TREE_OPERAND (ind, 0));
          sf = (tree) n->value;
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
-         src = build_fold_indirect_ref (sarg);
+         src = build_simple_mem_ref_loc (loc, sarg);
          src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
          src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
-         src = build_fold_indirect_ref (src);
-         dst = build_fold_indirect_ref (arg);
+         src = build_simple_mem_ref_loc (loc, src);
+         dst = build_simple_mem_ref_loc (loc, arg);
          dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
          t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
          append_to_statement_list (t, &list);
          dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
          t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
          append_to_statement_list (t, &list);
@@ -6355,10 +6654,10 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
                                 (splay_tree_key) TREE_OPERAND (ind, 0));
          df = (tree) n->value;
          df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
                                 (splay_tree_key) TREE_OPERAND (ind, 0));
          df = (tree) n->value;
          df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
-         ptr = build_fold_indirect_ref (arg);
+         ptr = build_simple_mem_ref_loc (loc, arg);
          ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
          t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
          ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
          t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
-                     build_fold_addr_expr (dst));
+                     build_fold_addr_expr_loc (loc, dst));
          append_to_statement_list (t, &list);
        }
 
          append_to_statement_list (t, &list);
        }
 
@@ -6385,6 +6684,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimple par_bind, bind;
   gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
   struct gimplify_ctx gctx;
   gimple par_bind, bind;
   gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
   struct gimplify_ctx gctx;
+  location_t loc = gimple_location (stmt);
 
   clauses = gimple_omp_taskreg_clauses (stmt);
   par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
 
   clauses = gimple_omp_taskreg_clauses (stmt);
   par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
@@ -6425,6 +6725,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       ctx->sender_decl
        = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
                          : ctx->record_type, ".omp_data_o");
       ctx->sender_decl
        = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
                          : ctx->record_type, ".omp_data_o");
+      DECL_NAMELESS (ctx->sender_decl) = 1;
       TREE_ADDRESSABLE (ctx->sender_decl) = 1;
       gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
     }
       TREE_ADDRESSABLE (ctx->sender_decl) = 1;
       gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
     }
@@ -6441,9 +6742,9 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   if (ctx->record_type)
     {
 
   if (ctx->record_type)
     {
-      t = build_fold_addr_expr (ctx->sender_decl);
+      t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
       /* fixup_child_record_type might have changed receiver_decl's type.  */
       /* fixup_child_record_type might have changed receiver_decl's type.  */
-      t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
+      t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
       gimple_seq_add_stmt (&new_body,
                           gimple_build_assign (ctx->receiver_decl, t));
     }
       gimple_seq_add_stmt (&new_body,
                           gimple_build_assign (ctx->receiver_decl, t));
     }
@@ -6512,7 +6813,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   /* If we have issued syntax errors, avoid doing any heavy lifting.
      Just replace the OpenMP directives with a NOP to avoid
      confusing RTL expansion.  */
   /* If we have issued syntax errors, avoid doing any heavy lifting.
      Just replace the OpenMP directives with a NOP to avoid
      confusing RTL expansion.  */
-  if (errorcount && is_gimple_omp (stmt))
+  if (seen_error () && is_gimple_omp (stmt))
     {
       gsi_replace (gsi_p, gimple_build_nop (), true);
       return;
     {
       gsi_replace (gsi_p, gimple_build_nop (), true);
       return;
@@ -6640,7 +6941,7 @@ execute_lower_omp (void)
   return 0;
 }
 
   return 0;
 }
 
-struct gimple_opt_pass pass_lower_omp = 
+struct gimple_opt_pass pass_lower_omp =
 {
  {
   GIMPLE_PASS,
 {
  {
   GIMPLE_PASS,
@@ -6655,7 +6956,7 @@ struct gimple_opt_pass pass_lower_omp =
   PROP_gimple_lomp,                    /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   PROP_gimple_lomp,                    /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
+  0                                     /* todo_flags_finish */
  }
 };
 \f
  }
 };
 \f
@@ -6675,7 +6976,7 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
   if (label_ctx == branch_ctx)
     return false;
 
   if (label_ctx == branch_ctx)
     return false;
 
-     
+
   /*
      Previously we kept track of the label's entire context in diagnose_sb_[12]
      so we could traverse it and issue a correct "exit" or "enter" error
   /*
      Previously we kept track of the label's entire context in diagnose_sb_[12]
      so we could traverse it and issue a correct "exit" or "enter" error
@@ -6686,7 +6987,7 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
      for issuing exit/enter error messages.  If someone really misses the
      distinct error message... patches welcome.
    */
      for issuing exit/enter error messages.  If someone really misses the
      distinct error message... patches welcome.
    */
-     
+
 #if 0
   /* Try to avoid confusing the user by producing and error message
      with correct "exit" or "enter" verbiage.  We prefer "exit"
 #if 0
   /* Try to avoid confusing the user by producing and error message
      with correct "exit" or "enter" verbiage.  We prefer "exit"
@@ -6739,7 +7040,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
  switch (gimple_code (stmt))
     {
     WALK_SUBSTMTS;
  switch (gimple_code (stmt))
     {
     WALK_SUBSTMTS;
-      
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
     case GIMPLE_OMP_SECTIONS:
@@ -6818,6 +7119,27 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
       wi->info = context;
       break;
 
       wi->info = context;
       break;
 
+    case GIMPLE_COND:
+       {
+         tree lab = gimple_cond_true_label (stmt);
+         if (lab)
+           {
+             n = splay_tree_lookup (all_labels,
+                                    (splay_tree_key) lab);
+             diagnose_sb_0 (gsi_p, context,
+                            n ? (gimple) n->value : NULL);
+           }
+         lab = gimple_cond_false_label (stmt);
+         if (lab)
+           {
+             n = splay_tree_lookup (all_labels,
+                                    (splay_tree_key) lab);
+             diagnose_sb_0 (gsi_p, context,
+                            n ? (gimple) n->value : NULL);
+           }
+       }
+      break;
+
     case GIMPLE_GOTO:
       {
        tree lab = gimple_goto_dest (stmt);
     case GIMPLE_GOTO:
       {
        tree lab = gimple_goto_dest (stmt);
@@ -6853,16 +7175,11 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
   return NULL_TREE;
 }
 
   return NULL_TREE;
 }
 
-void
-diagnose_omp_structured_block_errors (tree fndecl)
+static unsigned int
+diagnose_omp_structured_block_errors (void)
 {
 {
-  tree save_current = current_function_decl;
   struct walk_stmt_info wi;
   struct walk_stmt_info wi;
-  struct function *old_cfun = cfun;
-  gimple_seq body = gimple_body (fndecl);
-
-  current_function_decl = fndecl;
-  set_cfun (DECL_STRUCT_FUNCTION (fndecl));
+  gimple_seq body = gimple_body (current_function_decl);
 
   all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
 
 
   all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
 
@@ -6876,8 +7193,32 @@ diagnose_omp_structured_block_errors (tree fndecl)
   splay_tree_delete (all_labels);
   all_labels = NULL;
 
   splay_tree_delete (all_labels);
   all_labels = NULL;
 
-  set_cfun (old_cfun);
-  current_function_decl = save_current;
+  return 0;
 }
 
 }
 
+static bool
+gate_diagnose_omp_blocks (void)
+{
+  return flag_openmp != 0;
+}
+
+struct gimple_opt_pass pass_diagnose_omp_blocks =
+{
+  {
+    GIMPLE_PASS,
+    "*diagnose_omp_blocks",            /* name */
+    gate_diagnose_omp_blocks,          /* gate */
+    diagnose_omp_structured_block_errors,      /* execute */
+    NULL,                              /* sub */
+    NULL,                              /* next */
+    0,                                 /* static_pass_number */
+    TV_NONE,                           /* tv_id */
+    PROP_gimple_any,                   /* properties_required */
+    0,                                 /* properties_provided */
+    0,                                 /* properties_destroyed */
+    0,                                 /* todo_flags_start */
+    0,                                 /* todo_flags_finish */
+  }
+};
+
 #include "gt-omp-low.h"
 #include "gt-omp-low.h"