[multiple changes]
[gcc.git] / gcc / tree-nested.c
index fe938d913e18d190411aa95d650c033803f3e774..f2e6d3acfd72239b4472c05a528fee21123e1412 100644 (file)
@@ -1,6 +1,5 @@
 /* Nested function decomposition for GIMPLE.
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2004-2015 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
 #include "tree.h"
-#include "rtl.h"
+#include "fold-const.h"
+#include "stringpool.h"
+#include "stor-layout.h"
 #include "tm_p.h"
+#include "hard-reg-set.h"
 #include "function.h"
 #include "tree-dump.h"
 #include "tree-inline.h"
+#include "predict.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
 #include "gimple.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
 #include "tree-iterator.h"
-#include "tree-flow.h"
+#include "bitmap.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
 #include "cgraph.h"
-#include "expr.h"
+#include "tree-cfg.h"
+#include "hashtab.h"
+#include "rtl.h"
+#include "flags.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
+#include "expr.h"      /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL.  */
 #include "langhooks.h"
-#include "pointer-set.h"
-#include "ggc.h"
+#include "gimple-low.h"
+#include "gomp-constants.h"
 
 
 /* The object of this pass is to lower the representation of a set of nested
    nonlocal references.  We want to do this sooner rather than later, in
    order to give us more freedom in emitting all of the functions in question.
 
-   Back in olden times, when gcc was young, we developed an insanely 
+   Back in olden times, when gcc was young, we developed an insanely
    complicated scheme whereby variables which were referenced nonlocally
    were forced to live in the stack of the declaring function, and then
    the nested functions magically discovered where these variables were
    placed.  In order for this scheme to function properly, it required
-   that the outer function be partially expanded, then we switch to 
+   that the outer function be partially expanded, then we switch to
    compiling the inner function, and once done with those we switch back
    to compiling the outer function.  Such delicate ordering requirements
-   makes it difficult to do whole translation unit optimizations 
+   makes it difficult to do whole translation unit optimizations
    involving such functions.
 
    The implementation here is much more direct.  Everything that can be
    referenced by an inner function is a member of an explicitly created
    structure herein called the "nonlocal frame struct".  The incoming
-   static chain for a nested function is a pointer to this struct in 
+   static chain for a nested function is a pointer to this struct in
    the parent.  In this way, we settle on known offsets from a known
    base, and so are decoupled from the logic that places objects in the
    function's stack frame.  More importantly, we don't have to wait for
    allocated anywhere.  Which means that the outer function is now
    inlinable.
 
-   Theory of operation here is very simple.  Iterate over all the 
-   statements in all the functions (depth first) several times, 
+   Theory of operation here is very simple.  Iterate over all the
+   statements in all the functions (depth first) several times,
    allocating structures and fields on demand.  In general we want to
    examine inner functions first, so that we can avoid making changes
    to outer functions which are unnecessary.
@@ -83,9 +121,10 @@ struct nesting_info
   struct nesting_info *outer;
   struct nesting_info *inner;
   struct nesting_info *next;
-  
-  struct pointer_map_t *field_map;
-  struct pointer_map_t *var_map;
+
+  hash_map<tree, tree> *field_map;
+  hash_map<tree, tree> *var_map;
+  hash_set<tree *> *mem_refs;
   bitmap suppress_expansion;
 
   tree context;
@@ -149,7 +188,7 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
 
   tmp_var = create_tmp_var_raw (type, prefix);
   DECL_CONTEXT (tmp_var) = info->context;
-  TREE_CHAIN (tmp_var) = info->new_local_var_chain;
+  DECL_CHAIN (tmp_var) = info->new_local_var_chain;
   DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
   if (TREE_CODE (type) == COMPLEX_TYPE
       || TREE_CODE (type) == VECTOR_TYPE)
@@ -185,7 +224,7 @@ build_addr (tree exp, tree context)
      way the properties are for the ADDR_EXPR are computed properly.  */
   save_context = current_function_decl;
   current_function_decl = context;
-  retval = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
+  retval = build_fold_addr_expr (exp);
   current_function_decl = save_context;
   return retval;
 }
@@ -199,11 +238,11 @@ insert_field_into_struct (tree type, tree field)
 
   DECL_CONTEXT (field) = type;
 
-  for (p = &TYPE_FIELDS (type); *p ; p = &TREE_CHAIN (*p))
+  for (p = &TYPE_FIELDS (type); *p ; p = &DECL_CHAIN (*p))
     if (DECL_ALIGN (field) >= DECL_ALIGN (*p))
       break;
 
-  TREE_CHAIN (field) = *p;
+  DECL_CHAIN (field) = *p;
   *p = field;
 
   /* Set correct alignment for frame struct type.  */
@@ -236,6 +275,7 @@ get_frame_type (struct nesting_info *info)
 
       info->frame_type = type;
       info->frame_decl = create_tmp_var_for (info, type, "FRAME");
+      DECL_NONLOCAL_FRAME (info->frame_decl) = 1;
 
       /* ??? Always make it addressable for now, since it is meant to
         be pointed to by the static chain pointer.  This pessimizes
@@ -275,15 +315,13 @@ static tree
 lookup_field_for_decl (struct nesting_info *info, tree decl,
                       enum insert_option insert)
 {
-  void **slot;
-
   if (insert == NO_INSERT)
     {
-      slot = pointer_map_contains (info->field_map, decl);
-      return slot ? (tree) *slot : NULL_TREE;
+      tree *slot = info->field_map->get (decl);
+      return slot ? *slot : NULL_TREE;
     }
 
-  slot = pointer_map_insert (info->field_map, decl);
+  tree *slot = &info->field_map->get_or_insert (decl);
   if (!*slot)
     {
       tree field = make_node (FIELD_DECL);
@@ -313,7 +351,7 @@ lookup_field_for_decl (struct nesting_info *info, tree decl,
        info->any_parm_remapped = true;
     }
 
-  return (tree) *slot;
+  return *slot;
 }
 
 /* Build or return the variable that holds the static chain within
@@ -335,7 +373,7 @@ get_chain_decl (struct nesting_info *info)
         the construction of this variable is handled specially in
         expand_function_start and initialize_inlined_parameters.
         Note also that it's represented as a parameter.  This is more
-        close to the truth, since the initial value does come from 
+        close to the truth, since the initial value does come from
         the caller.  */
       decl = build_decl (DECL_SOURCE_LOCATION (info->context),
                         PARM_DECL, create_tmp_var_name ("CHAIN"), type);
@@ -353,11 +391,11 @@ get_chain_decl (struct nesting_info *info)
 
       if (dump_file
           && (dump_flags & TDF_DETAILS)
-         && DECL_NO_STATIC_CHAIN (info->context))
-       fprintf (dump_file, "Resetting no-static-chain for %s\n",
+         && !DECL_STATIC_CHAIN (info->context))
+       fprintf (dump_file, "Setting static-chain for %s\n",
                 lang_hooks.decl_printable_name (info->context, 2));
 
-      DECL_NO_STATIC_CHAIN (info->context) = 0;
+      DECL_STATIC_CHAIN (info->context) = 1;
     }
   return decl;
 }
@@ -387,11 +425,11 @@ get_chain_field (struct nesting_info *info)
 
       if (dump_file
           && (dump_flags & TDF_DETAILS)
-         && DECL_NO_STATIC_CHAIN (info->context))
-       fprintf (dump_file, "Resetting no-static-chain for %s\n",
+         && !DECL_STATIC_CHAIN (info->context))
+       fprintf (dump_file, "Setting static-chain for %s\n",
                 lang_hooks.decl_printable_name (info->context, 2));
 
-      DECL_NO_STATIC_CHAIN (info->context) = 0;
+      DECL_STATIC_CHAIN (info->context) = 1;
     }
   return field;
 }
@@ -400,7 +438,7 @@ get_chain_field (struct nesting_info *info)
 
 static tree
 init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
-                       gimple call)
+                       gcall *call)
 {
   tree t;
 
@@ -413,7 +451,7 @@ init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
   return t;
 }
 
-  
+
 /* Copy EXP into a temporary.  Allocate the temporary in the context of
    INFO and insert the initialization statement before GSI.  */
 
@@ -487,7 +525,7 @@ get_trampoline_type (struct nesting_info *info)
       align = STACK_BOUNDARY;
     }
 
-  t = build_index_type (build_int_cst (NULL_TREE, size - 1));
+  t = build_index_type (size_int (size - 1));
   t = build_array_type (char_type_node, t);
   t = build_decl (DECL_SOURCE_LOCATION (info->context),
                  FIELD_DECL, get_identifier ("__data"), t);
@@ -510,15 +548,13 @@ static tree
 lookup_tramp_for_decl (struct nesting_info *info, tree decl,
                       enum insert_option insert)
 {
-  void **slot;
-
   if (insert == NO_INSERT)
     {
-      slot = pointer_map_contains (info->var_map, decl);
-      return slot ? (tree) *slot : NULL_TREE;
+      tree *slot = info->var_map->get (decl);
+      return slot ? *slot : NULL_TREE;
     }
 
-  slot = pointer_map_insert (info->var_map, decl);
+  tree *slot = &info->var_map->get_or_insert (decl);
   if (!*slot)
     {
       tree field = make_node (FIELD_DECL);
@@ -532,8 +568,8 @@ lookup_tramp_for_decl (struct nesting_info *info, tree decl,
       info->any_tramp_created = true;
     }
 
-  return (tree) *slot;
-} 
+  return *slot;
+}
 
 /* Build or return the field within the non-local frame state that holds
    the non-local goto "jmp_buf".  The buffer itself is maintained by the
@@ -562,7 +598,7 @@ get_nl_goto_field (struct nesting_info *info)
       size = size + 1;
 
       type = build_array_type
-       (type, build_index_type (build_int_cst (NULL_TREE, size)));
+       (type, build_index_type (size_int (size)));
 
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = get_identifier ("__nl_goto_buf");
@@ -578,18 +614,18 @@ get_nl_goto_field (struct nesting_info *info)
   return field;
 }
 
-/* Invoke CALLBACK on all statements of GIMPLE sequence SEQ.  */
+/* Invoke CALLBACK on all statements of GIMPLE sequence *PSEQ.  */
 
 static void
 walk_body (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
-          struct nesting_info *info, gimple_seq seq)
+          struct nesting_info *info, gimple_seq *pseq)
 {
   struct walk_stmt_info wi;
 
   memset (&wi, 0, sizeof (wi));
   wi.info = info;
   wi.val_only = true;
-  walk_gimple_seq (seq, callback_stmt, callback_op, &wi);
+  walk_gimple_seq_mod (pseq, callback_stmt, callback_op, &wi);
 }
 
 
@@ -599,13 +635,15 @@ static inline void
 walk_function (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
               struct nesting_info *info)
 {
-  walk_body (callback_stmt, callback_op, info, gimple_body (info->context));
+  gimple_seq body = gimple_body (info->context);
+  walk_body (callback_stmt, callback_op, info, &body);
+  gimple_set_body (info->context, body);
 }
 
 /* Invoke CALLBACK on a GIMPLE_OMP_FOR's init, cond, incr and pre-body.  */
 
 static void
-walk_gimple_omp_for (gimple for_stmt,
+walk_gimple_omp_for (gomp_for *for_stmt,
                     walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
                     struct nesting_info *info)
 {
@@ -614,9 +652,9 @@ walk_gimple_omp_for (gimple for_stmt,
   tree t;
   size_t i;
 
-  walk_body (callback_stmt, callback_op, info, gimple_omp_for_pre_body (for_stmt));
+  walk_body (callback_stmt, callback_op, info, gimple_omp_for_pre_body_ptr (for_stmt));
 
-  seq = gimple_seq_alloc ();
+  seq = NULL;
   memset (&wi, 0, sizeof (wi));
   wi.info = info;
   wi.gsi = gsi_last (seq);
@@ -645,9 +683,8 @@ walk_gimple_omp_for (gimple for_stmt,
       walk_tree (&TREE_OPERAND (t, 1), callback_op, &wi, NULL);
     }
 
-  if (gimple_seq_empty_p (seq))
-    gimple_seq_free (seq);
-  else
+  seq = gsi_seq (wi.gsi);
+  if (!gimple_seq_empty_p (seq))
     {
       gimple_seq pre_body = gimple_omp_for_pre_body (for_stmt);
       annotate_all_with_location (seq, gimple_location (for_stmt));
@@ -657,7 +694,7 @@ walk_gimple_omp_for (gimple for_stmt,
 }
 
 /* Similarly for ROOT and all functions nested underneath, depth first.  */
-    
+
 static void
 walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
                    struct nesting_info *root)
@@ -694,16 +731,17 @@ walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
 static bool
 check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
+  struct cgraph_node *cgn = cgraph_node::get (fndecl);
   tree arg;
 
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
     {
-      for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = TREE_CHAIN (arg))
+      for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg))
        if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl))
          return true;
 
-      if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl))
+      if (check_for_nested_with_variably_modified (cgn->decl,
+                                                  orig_fndecl))
        return true;
     }
 
@@ -717,8 +755,9 @@ static struct nesting_info *
 create_nesting_tree (struct cgraph_node *cgn)
 {
   struct nesting_info *info = XCNEW (struct nesting_info);
-  info->field_map = pointer_map_create ();
-  info->var_map = pointer_map_create ();
+  info->field_map = new hash_map<tree, tree>;
+  info->var_map = new hash_map<tree, tree>;
+  info->mem_refs = new hash_set<tree *>;
   info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
   info->context = cgn->decl;
 
@@ -760,7 +799,7 @@ get_static_chain (struct nesting_info *info, tree target_context,
        {
          tree field = get_chain_field (i);
 
-         x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+         x = build_simple_mem_ref (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, gsi);
        }
@@ -795,12 +834,12 @@ get_frame_field (struct nesting_info *info, tree target_context,
        {
          tree field = get_chain_field (i);
 
-         x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+         x = build_simple_mem_ref (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, gsi);
        }
 
-      x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+      x = build_simple_mem_ref (x);
     }
 
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
@@ -811,8 +850,8 @@ static void note_nonlocal_vla_type (struct nesting_info *info, tree type);
 
 /* A subroutine of convert_nonlocal_reference_op.  Create a local variable
    in the nested function with DECL_VALUE_EXPR set to reference the true
-   variable in the parent function.  This is used both for debug info 
-   and in OpenMP lowering.  */
+   variable in the parent function.  This is used both for debug info
+   and in OMP lowering.  */
 
 static tree
 get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
@@ -820,12 +859,11 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
   tree target_context;
   struct nesting_info *i;
   tree x, field, new_decl;
-  void **slot;
 
-  slot = pointer_map_insert (info->var_map, decl);
+  tree *slot = &info->var_map->get_or_insert (decl);
 
   if (*slot)
-    return (tree) *slot;
+    return *slot;
 
   target_context = decl_function_context (decl);
 
@@ -843,16 +881,16 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
       for (i = info->outer; i->context != target_context; i = i->outer)
        {
          field = get_chain_field (i);
-         x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+         x = build_simple_mem_ref (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
        }
-      x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+      x = build_simple_mem_ref (x);
     }
 
   field = lookup_field_for_decl (i, decl, INSERT);
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
   if (use_pointer_in_frame (decl))
-    x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+    x = build_simple_mem_ref (x);
 
   /* ??? We should be remapping types as well, surely.  */
   new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
@@ -875,7 +913,7 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
   DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
 
   *slot = new_decl;
-  TREE_CHAIN (new_decl) = info->debug_var_chain;
+  DECL_CHAIN (new_decl) = info->debug_var_chain;
   info->debug_var_chain = new_decl;
 
   if (!optimize
@@ -929,7 +967,7 @@ convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data)
              if (use_pointer_in_frame (t))
                {
                  x = init_tmp_var (info, x, &wi->gsi);
-                 x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+                 x = build_simple_mem_ref (x);
                }
            }
 
@@ -1011,13 +1049,6 @@ convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data)
              walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference_op,
                         wi, NULL);
            }
-         else if (TREE_CODE (t) == BIT_FIELD_REF)
-           {
-             walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op,
-                        wi, NULL);
-             walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op,
-                        wi, NULL);
-           }
        }
       wi->val_only = false;
       walk_tree (tp, convert_nonlocal_reference_op, wi, NULL);
@@ -1075,6 +1106,15 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
            need_stmts = true;
          goto do_decl_clause;
 
+       case OMP_CLAUSE_LINEAR:
+         if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause))
+           need_stmts = true;
+         wi->val_only = true;
+         wi->is_lhs = false;
+         convert_nonlocal_reference_op (&OMP_CLAUSE_LINEAR_STEP (clause),
+                                        &dummy, wi);
+         goto do_decl_clause;
+
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_COPYPRIVATE:
@@ -1088,7 +1128,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
            {
              bitmap_set_bit (new_suppress, DECL_UID (decl));
              OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
-             need_chain = true;
+             if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
+               need_chain = true;
            }
          break;
 
@@ -1096,12 +1137,68 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
            break;
          /* FALLTHRU */
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_DEPEND:
+       case OMP_CLAUSE_DEVICE:
+       case OMP_CLAUSE_NUM_TEAMS:
+       case OMP_CLAUSE_THREAD_LIMIT:
+       case OMP_CLAUSE_SAFELEN:
+       case OMP_CLAUSE__CILK_FOR_COUNT_:
          wi->val_only = true;
          wi->is_lhs = false;
          convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
-                                        &dummy, wi);
+                                        &dummy, wi);
+         break;
+
+       case OMP_CLAUSE_DIST_SCHEDULE:
+         if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause) != NULL)
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+                                            &dummy, wi);
+           }
+         break;
+
+       case OMP_CLAUSE_MAP:
+       case OMP_CLAUSE_TO:
+       case OMP_CLAUSE_FROM:
+         if (OMP_CLAUSE_SIZE (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op (&OMP_CLAUSE_SIZE (clause),
+                                            &dummy, wi);
+           }
+         if (DECL_P (OMP_CLAUSE_DECL (clause)))
+           goto do_decl_clause;
+         wi->val_only = true;
+         wi->is_lhs = false;
+         walk_tree (&OMP_CLAUSE_DECL (clause), convert_nonlocal_reference_op,
+                    wi, NULL);
+         break;
+
+       case OMP_CLAUSE_ALIGNED:
+         if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op
+               (&OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), &dummy, wi);
+           }
+         /* Like do_decl_clause, but don't add any suppression.  */
+         decl = OMP_CLAUSE_DECL (clause);
+         if (TREE_CODE (decl) == VAR_DECL
+             && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+           break;
+         if (decl_function_context (decl) != info->context)
+           {
+             OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
+             if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
+               need_chain = true;
+           }
          break;
 
        case OMP_CLAUSE_NOWAIT:
@@ -1110,6 +1207,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
+       case OMP_CLAUSE_PROC_BIND:
          break;
 
        default:
@@ -1132,10 +1231,10 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                = info->context;
              walk_body (convert_nonlocal_reference_stmt,
                         convert_nonlocal_reference_op, info,
-                        OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
+                        &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
              walk_body (convert_nonlocal_reference_stmt,
                         convert_nonlocal_reference_op, info,
-                        OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
+                        &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
              DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
                = old_context;
            }
@@ -1144,7 +1243,13 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_LASTPRIVATE:
          walk_body (convert_nonlocal_reference_stmt,
                     convert_nonlocal_reference_op, info,
-                    OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+                    &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+         break;
+
+       case OMP_CLAUSE_LINEAR:
+         walk_body (convert_nonlocal_reference_stmt,
+                    convert_nonlocal_reference_op, info,
+                    &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause));
          break;
 
        default:
@@ -1201,7 +1306,7 @@ note_nonlocal_block_vlas (struct nesting_info *info, tree block)
 {
   tree var;
 
-  for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
+  for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
     if (TREE_CODE (var) == VAR_DECL
        && variably_modified_type_p (TREE_TYPE (var), NULL)
        && DECL_HAS_VALUE_EXPR_P (var)
@@ -1257,7 +1362,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->new_local_var_chain = NULL;
 
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
 
       if (info->new_local_var_chain)
        declare_vars (info->new_local_var_chain,
@@ -1270,10 +1375,11 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_FOR:
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi);
-      walk_gimple_omp_for (stmt, convert_nonlocal_reference_stmt,
+      walk_gimple_omp_for (as_a <gomp_for *> (stmt),
+                          convert_nonlocal_reference_stmt,
                           convert_nonlocal_reference_op, info);
       walk_body (convert_nonlocal_reference_stmt,
-                convert_nonlocal_reference_op, info, gimple_omp_body (stmt));
+                convert_nonlocal_reference_op, info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1281,7 +1387,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1289,23 +1395,99 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
+      info->suppress_expansion = save_suppress;
+      break;
+
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         save_suppress = info->suppress_expansion;
+         convert_nonlocal_omp_clauses (gimple_omp_target_clauses_ptr (stmt),
+                                       wi);
+         info->suppress_expansion = save_suppress;
+         walk_body (convert_nonlocal_reference_stmt,
+                    convert_nonlocal_reference_op, info,
+                    gimple_omp_body_ptr (stmt));
+         break;
+       }
+      save_suppress = info->suppress_expansion;
+      if (convert_nonlocal_omp_clauses (gimple_omp_target_clauses_ptr (stmt),
+                                       wi))
+       {
+         tree c, decl;
+         decl = get_chain_decl (info);
+         c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+         OMP_CLAUSE_DECL (c) = decl;
+         OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
+         OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+         gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+       }
+
+      save_local_var_chain = info->new_local_var_chain;
+      info->new_local_var_chain = NULL;
+
+      walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+                info, gimple_omp_body_ptr (stmt));
+
+      if (info->new_local_var_chain)
+       declare_vars (info->new_local_var_chain,
+                     gimple_seq_first_stmt (gimple_omp_body (stmt)),
+                     false);
+      info->new_local_var_chain = save_local_var_chain;
+      info->suppress_expansion = save_suppress;
+      break;
+
+    case GIMPLE_OMP_TEAMS:
+      save_suppress = info->suppress_expansion;
+      convert_nonlocal_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
+      walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+                info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
+    case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
       break;
 
     case GIMPLE_BIND:
-      if (!optimize && gimple_bind_block (stmt))
-       note_nonlocal_block_vlas (info, gimple_bind_block (stmt));
+      {
+      gbind *bind_stmt = as_a <gbind *> (stmt);
+      if (!optimize && gimple_bind_block (bind_stmt))
+       note_nonlocal_block_vlas (info, gimple_bind_block (bind_stmt));
+
+      for (tree var = gimple_bind_vars (bind_stmt); var; var = DECL_CHAIN (var))
+       if (TREE_CODE (var) == NAMELIST_DECL)
+         {
+           /* Adjust decls mentioned in NAMELIST_DECL.  */
+           tree decls = NAMELIST_DECL_ASSOCIATED_DECL (var);
+           tree decl;
+           unsigned int i;
+
+           FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (decls), i, decl)
+             {
+               if (TREE_CODE (decl) == VAR_DECL
+                   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+                 continue;
+               if (decl_function_context (decl) != info->context)
+                 CONSTRUCTOR_ELT (decls, i)->value
+                   = get_nonlocal_debug_decl (info, decl);
+             }
+         }
 
       *handled_ops_p = false;
       return NULL_TREE;
+      }
+    case GIMPLE_COND:
+      wi->val_only = true;
+      wi->is_lhs = false;
+      *handled_ops_p = false;
+      return NULL_TREE;
 
     default:
       /* For every other statement that we are not interested in
@@ -1322,18 +1504,17 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
 /* A subroutine of convert_local_reference.  Create a local variable
    in the parent function with DECL_VALUE_EXPR set to reference the
-   field in FRAME.  This is used both for debug info and in OpenMP
+   field in FRAME.  This is used both for debug info and in OMP
    lowering.  */
 
 static tree
 get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
 {
   tree x, new_decl;
-  void **slot;
 
-  slot = pointer_map_insert (info->var_map, decl);
+  tree *slot = &info->var_map->get_or_insert (decl);
   if (*slot)
-    return (tree) *slot;
+    return *slot;
 
   /* Make sure frame_decl gets created.  */
   (void) get_frame_type (info);
@@ -1360,7 +1541,7 @@ get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
   DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
   *slot = new_decl;
 
-  TREE_CHAIN (new_decl) = info->debug_var_chain;
+  DECL_CHAIN (new_decl) = info->debug_var_chain;
   info->debug_var_chain = new_decl;
 
   /* Do not emit debug info twice.  */
@@ -1439,7 +1620,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
 
          /* Then the frame decl is now addressable.  */
          TREE_ADDRESSABLE (info->frame_decl) = 1;
-           
+
          save_context = current_function_decl;
          current_function_decl = info->context;
          recompute_tree_invariant_for_addr_expr (t);
@@ -1480,19 +1661,27 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
              walk_tree (&TREE_OPERAND (t, 3), convert_local_reference_op, wi,
                         NULL);
            }
-         else if (TREE_CODE (t) == BIT_FIELD_REF)
-           {
-             walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi,
-                        NULL);
-             walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
-                        NULL);
-           }
        }
       wi->val_only = false;
       walk_tree (tp, convert_local_reference_op, wi, NULL);
       wi->val_only = save_val_only;
       break;
 
+    case MEM_REF:
+      save_val_only = wi->val_only;
+      wi->val_only = true;
+      wi->is_lhs = false;
+      walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op,
+                wi, NULL);
+      /* We need to re-fold the MEM_REF as component references as
+        part of a ADDR_EXPR address are not allowed.  But we cannot
+        fold here, as the chain record type is not yet finalized.  */
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+         && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
+       info->mem_refs->add (tp);
+      wi->val_only = save_val_only;
+      break;
+
     case VIEW_CONVERT_EXPR:
       /* Just request to look at the subtrees, leaving val_only and lhs
         untouched.  This might actually be for !val_only + lhs, in which
@@ -1545,6 +1734,15 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
            need_stmts = true;
          goto do_decl_clause;
 
+       case OMP_CLAUSE_LINEAR:
+         if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause))
+           need_stmts = true;
+         wi->val_only = true;
+         wi->is_lhs = false;
+         convert_local_reference_op (&OMP_CLAUSE_LINEAR_STEP (clause), &dummy,
+                                     wi);
+         goto do_decl_clause;
+
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_COPYPRIVATE:
@@ -1572,20 +1770,83 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
            break;
          /* FALLTHRU */
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_DEPEND:
+       case OMP_CLAUSE_DEVICE:
+       case OMP_CLAUSE_NUM_TEAMS:
+       case OMP_CLAUSE_THREAD_LIMIT:
+       case OMP_CLAUSE_SAFELEN:
+       case OMP_CLAUSE__CILK_FOR_COUNT_:
          wi->val_only = true;
          wi->is_lhs = false;
          convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
                                      wi);
          break;
 
+       case OMP_CLAUSE_DIST_SCHEDULE:
+         if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause) != NULL)
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+                                         &dummy, wi);
+           }
+         break;
+
+       case OMP_CLAUSE_MAP:
+       case OMP_CLAUSE_TO:
+       case OMP_CLAUSE_FROM:
+         if (OMP_CLAUSE_SIZE (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op (&OMP_CLAUSE_SIZE (clause),
+                                         &dummy, wi);
+           }
+         if (DECL_P (OMP_CLAUSE_DECL (clause)))
+           goto do_decl_clause;
+         wi->val_only = true;
+         wi->is_lhs = false;
+         walk_tree (&OMP_CLAUSE_DECL (clause), convert_local_reference_op,
+                    wi, NULL);
+         break;
+
+       case OMP_CLAUSE_ALIGNED:
+         if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op
+               (&OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), &dummy, wi);
+           }
+         /* Like do_decl_clause, but don't add any suppression.  */
+         decl = OMP_CLAUSE_DECL (clause);
+         if (TREE_CODE (decl) == VAR_DECL
+             && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+           break;
+         if (decl_function_context (decl) == info->context
+             && !use_pointer_in_frame (decl))
+           {
+             tree field = lookup_field_for_decl (info, decl, NO_INSERT);
+             if (field)
+               {
+                 OMP_CLAUSE_DECL (clause)
+                   = get_local_debug_decl (info, decl, field);
+                 need_frame = true;
+               }
+           }
+         break;
+
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
+       case OMP_CLAUSE_PROC_BIND:
          break;
 
        default:
@@ -1608,10 +1869,10 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                = info->context;
              walk_body (convert_local_reference_stmt,
                         convert_local_reference_op, info,
-                        OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
+                        &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
              walk_body (convert_local_reference_stmt,
                         convert_local_reference_op, info,
-                        OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
+                        &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
              DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
                = old_context;
            }
@@ -1620,7 +1881,13 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_LASTPRIVATE:
          walk_body (convert_local_reference_stmt,
                     convert_local_reference_op, info,
-                    OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+                    &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+         break;
+
+       case OMP_CLAUSE_LINEAR:
+         walk_body (convert_local_reference_stmt,
+                    convert_local_reference_op, info,
+                    &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause));
          break;
 
        default:
@@ -1665,7 +1932,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->new_local_var_chain = NULL;
 
       walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
-                gimple_omp_body (stmt));
+                gimple_omp_body_ptr (stmt));
 
       if (info->new_local_var_chain)
        declare_vars (info->new_local_var_chain,
@@ -1677,10 +1944,11 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_FOR:
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi);
-      walk_gimple_omp_for (stmt, convert_local_reference_stmt,
+      walk_gimple_omp_for (as_a <gomp_for *> (stmt),
+                          convert_local_reference_stmt,
                           convert_local_reference_op, info);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1688,7 +1956,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1696,17 +1964,114 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
+      info->suppress_expansion = save_suppress;
+      break;
+
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         save_suppress = info->suppress_expansion;
+         convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi);
+         info->suppress_expansion = save_suppress;
+         walk_body (convert_local_reference_stmt, convert_local_reference_op,
+                    info, gimple_omp_body_ptr (stmt));
+         break;
+       }
+      save_suppress = info->suppress_expansion;
+      if (convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi))
+       {
+         tree c;
+         (void) get_frame_type (info);
+         c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
+         OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
+         OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl);
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+         gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+       }
+
+      save_local_var_chain = info->new_local_var_chain;
+      info->new_local_var_chain = NULL;
+
+      walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
+                gimple_omp_body_ptr (stmt));
+
+      if (info->new_local_var_chain)
+       declare_vars (info->new_local_var_chain,
+                     gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
+      info->new_local_var_chain = save_local_var_chain;
+      info->suppress_expansion = save_suppress;
+      break;
+
+    case GIMPLE_OMP_TEAMS:
+      save_suppress = info->suppress_expansion;
+      convert_local_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
+      walk_body (convert_local_reference_stmt, convert_local_reference_op,
+                info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
+    case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-                info, gimple_omp_body (stmt));
+                info, gimple_omp_body_ptr (stmt));
       break;
 
+    case GIMPLE_COND:
+      wi->val_only = true;
+      wi->is_lhs = false;
+      *handled_ops_p = false;
+      return NULL_TREE;
+
+    case GIMPLE_ASSIGN:
+      if (gimple_clobber_p (stmt))
+       {
+         tree lhs = gimple_assign_lhs (stmt);
+         if (!use_pointer_in_frame (lhs)
+             && lookup_field_for_decl (info, lhs, NO_INSERT))
+           {
+             gsi_replace (gsi, gimple_build_nop (), true);
+             break;
+           }
+       }
+      *handled_ops_p = false;
+      return NULL_TREE;
+
+    case GIMPLE_BIND:
+      for (tree var = gimple_bind_vars (as_a <gbind *> (stmt));
+          var;
+          var = DECL_CHAIN (var))
+       if (TREE_CODE (var) == NAMELIST_DECL)
+         {
+           /* Adjust decls mentioned in NAMELIST_DECL.  */
+           tree decls = NAMELIST_DECL_ASSOCIATED_DECL (var);
+           tree decl;
+           unsigned int i;
+
+           FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (decls), i, decl)
+             {
+               if (TREE_CODE (decl) == VAR_DECL
+                   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+                 continue;
+               if (decl_function_context (decl) == info->context
+                   && !use_pointer_in_frame (decl))
+                 {
+                   tree field = lookup_field_for_decl (info, decl, NO_INSERT);
+                   if (field)
+                     {
+                       CONSTRUCTOR_ELT (decls, i)->value
+                         = get_local_debug_decl (info, decl, field);
+                     }
+                 }
+             }
+         }
+
+      *handled_ops_p = false;
+      return NULL_TREE;
+
     default:
       /* For every other statement that we are not interested in
         handling here, let the walker traverse the operands.  */
@@ -1730,8 +2095,7 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 {
   struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
   tree label, new_label, target_context, x, field;
-  void **slot;
-  gimple call;
+  gcall *call;
   gimple stmt = gsi_stmt (*gsi);
 
   if (gimple_code (stmt) != GIMPLE_GOTO)
@@ -1764,7 +2128,7 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
      (hairy target-specific) non-local goto receiver code to be generated
      when we expand rtl.  Enter this association into var_map so that we
      can insert the new label into the IL during a second pass.  */
-  slot = pointer_map_insert (i->var_map, label);
+  tree *slot = &i->var_map->get_or_insert (label);
   if (*slot == NULL)
     {
       new_label = create_artificial_label (UNKNOWN_LOCATION);
@@ -1772,16 +2136,16 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       *slot = new_label;
     }
   else
-    new_label = (tree) *slot;
-  
+    new_label = *slot;
+
   /* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field).  */
   field = get_nl_goto_field (i);
-  x = get_frame_field (info, target_context, field, &wi->gsi);
+  x = get_frame_field (info, target_context, field, gsi);
   x = build_addr (x, target_context);
-  x = gsi_gimplify_val (info, x, &wi->gsi);
-  call = gimple_build_call (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2,
-                           build_addr (new_label, target_context), x);
-  gsi_replace (&wi->gsi, call, false);
+  x = gsi_gimplify_val (info, x, gsi);
+  call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO),
+                           2, build_addr (new_label, target_context), x);
+  gsi_replace (gsi, call, false);
 
   /* We have handled all of STMT's operands, no need to keep going.  */
   *handled_ops_p = true;
@@ -1802,10 +2166,9 @@ convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   struct nesting_info *const info = (struct nesting_info *) wi->info;
   tree label, new_label;
   gimple_stmt_iterator tmp_gsi;
-  void **slot;
-  gimple stmt = gsi_stmt (*gsi);
+  glabel *stmt = dyn_cast <glabel *> (gsi_stmt (*gsi));
 
-  if (gimple_code (stmt) != GIMPLE_LABEL)
+  if (!stmt)
     {
       *handled_ops_p = false;
       return NULL_TREE;
@@ -1813,7 +2176,7 @@ convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
   label = gimple_label_label (stmt);
 
-  slot = pointer_map_contains (info->var_map, label);
+  tree *slot = info->var_map->get (label);
   if (!slot)
     {
       *handled_ops_p = false;
@@ -1849,7 +2212,7 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
   tree t = *tp, decl, target_context, x, builtin;
-  gimple call;
+  gcall *call;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
@@ -1872,7 +2235,7 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
 
       /* If the nested function doesn't use a static chain, then
         it doesn't need a trampoline.  */
-      if (DECL_NO_STATIC_CHAIN (decl))
+      if (!DECL_STATIC_CHAIN (decl))
        break;
 
       /* If we don't want a trampoline, then don't build one.  */
@@ -1892,7 +2255,7 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
 
       /* Do machine-specific ugliness.  Normally this will involve
         computing extra alignment, but it can really be anything.  */
-      builtin = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
+      builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
       call = gimple_build_call (builtin, 1, x);
       x = init_tmp_var_with_call (info, &wi->gsi, call);
 
@@ -1922,6 +2285,7 @@ static tree
 convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
                              struct walk_stmt_info *wi)
 {
+  struct nesting_info *info = (struct nesting_info *) wi->info;
   gimple stmt = gsi_stmt (*gsi);
 
   switch (gimple_code (stmt))
@@ -1934,16 +2298,39 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        for (i = 0; i < nargs; i++)
          walk_tree (gimple_call_arg_ptr (stmt, i), convert_tramp_reference_op,
                     wi, NULL);
+       break;
+      }
 
-       *handled_ops_p = true;
-       return NULL_TREE;
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         *handled_ops_p = false;
+         return NULL_TREE;
+       }
+      /* FALLTHRU */
+    case GIMPLE_OMP_PARALLEL:
+    case GIMPLE_OMP_TASK:
+      {
+       tree save_local_var_chain;
+        walk_gimple_op (stmt, convert_tramp_reference_op, wi);
+       save_local_var_chain = info->new_local_var_chain;
+       info->new_local_var_chain = NULL;
+        walk_body (convert_tramp_reference_stmt, convert_tramp_reference_op,
+                  info, gimple_omp_body_ptr (stmt));
+       if (info->new_local_var_chain)
+         declare_vars (info->new_local_var_chain,
+                       gimple_seq_first_stmt (gimple_omp_body (stmt)),
+                       false);
+       info->new_local_var_chain = save_local_var_chain;
       }
+      break;
 
     default:
-      break;
+      *handled_ops_p = false;
+      return NULL_TREE;
     }
 
-  *handled_ops_p = false;
+  *handled_ops_p = true;
   return NULL_TREE;
 }
 
@@ -1972,10 +2359,11 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       if (!decl)
        break;
       target_context = decl_function_context (decl);
-      if (target_context && !DECL_NO_STATIC_CHAIN (decl))
+      if (target_context && DECL_STATIC_CHAIN (decl))
        {
-         gimple_call_set_chain (stmt, get_static_chain (info, target_context,
-                                                        &wi->gsi));
+         gimple_call_set_chain (as_a <gcall *> (stmt),
+                                get_static_chain (info, target_context,
+                                                  &wi->gsi));
          info->static_chain_added |= (1 << (info->context != target_context));
        }
       break;
@@ -1984,7 +2372,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_TASK:
       save_static_chain_added = info->static_chain_added;
       info->static_chain_added = 0;
-      walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
+      walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       for (i = 0; i < 2; i++)
        {
          tree c, decl;
@@ -2012,17 +2400,55 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->static_chain_added |= save_static_chain_added;
       break;
 
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
+         break;
+       }
+      save_static_chain_added = info->static_chain_added;
+      info->static_chain_added = 0;
+      walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
+      for (i = 0; i < 2; i++)
+       {
+         tree c, decl;
+         if ((info->static_chain_added & (1 << i)) == 0)
+           continue;
+         decl = i ? get_chain_decl (info) : info->frame_decl;
+         /* Don't add CHAIN.* or FRAME.* twice.  */
+         for (c = gimple_omp_target_clauses (stmt);
+              c;
+              c = OMP_CLAUSE_CHAIN (c))
+           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+               && OMP_CLAUSE_DECL (c) == decl)
+             break;
+         if (c == NULL)
+           {
+             c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+             OMP_CLAUSE_DECL (c) = decl;
+             OMP_CLAUSE_SET_MAP_KIND (c, i ? GOMP_MAP_TO : GOMP_MAP_TOFROM);
+             OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
+             OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+             gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt),
+                                            c);
+           }
+       }
+      info->static_chain_added |= save_static_chain_added;
+      break;
+
     case GIMPLE_OMP_FOR:
       walk_body (convert_gimple_call, NULL, info,
-                gimple_omp_for_pre_body (stmt));
+                gimple_omp_for_pre_body_ptr (stmt));
       /* FALLTHRU */
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_SINGLE:
+    case GIMPLE_OMP_TEAMS:
     case GIMPLE_OMP_MASTER:
+    case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
     case GIMPLE_OMP_CRITICAL:
-      walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
+      walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       break;
 
     default:
@@ -2042,37 +2468,48 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 static void
 convert_all_function_calls (struct nesting_info *root)
 {
+  unsigned int chain_count = 0, old_chain_count, iter_count;
   struct nesting_info *n;
-  int iter_count;
-  bool any_changed;
 
-  /* First, optimistically set no_static_chain for all decls that haven't
-     used the static chain already for variable access.  */
+  /* First, optimistically clear static_chain for all decls that haven't
+     used the static chain already for variable access.  But always create
+     it if not optimizing.  This makes it possible to reconstruct the static
+     nesting tree at run time and thus to resolve up-level references from
+     within the debugger.  */
   FOR_EACH_NEST_INFO (n, root)
     {
       tree decl = n->context;
-      if (n->outer && !n->chain_decl && !n->chain_field)
+      if (!optimize)
        {
-         DECL_NO_STATIC_CHAIN (decl) = 1;
+         if (n->inner)
+           (void) get_frame_type (n);
+         if (n->outer)
+           (void) get_chain_decl (n);
+       }
+      else if (!n->outer || (!n->chain_decl && !n->chain_field))
+       {
+         DECL_STATIC_CHAIN (decl) = 0;
          if (dump_file && (dump_flags & TDF_DETAILS))
-           fprintf (dump_file, "Guessing no-static-chain for %s\n",
+           fprintf (dump_file, "Guessing no static-chain for %s\n",
                     lang_hooks.decl_printable_name (decl, 2));
        }
       else
-       gcc_assert (!DECL_NO_STATIC_CHAIN (decl));
+       DECL_STATIC_CHAIN (decl) = 1;
+      chain_count += DECL_STATIC_CHAIN (decl);
     }
 
   /* Walk the functions and perform transformations.  Note that these
      transformations can induce new uses of the static chain, which in turn
      require re-examining all users of the decl.  */
   /* ??? It would make sense to try to use the call graph to speed this up,
-     but the call graph hasn't really been built yet.  Even if it did, we 
+     but the call graph hasn't really been built yet.  Even if it did, we
      would still need to iterate in this loop since address-of references
      wouldn't show up in the callgraph anyway.  */
   iter_count = 0;
   do
     {
-      any_changed = false;
+      old_chain_count = chain_count;
+      chain_count = 0;
       iter_count++;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2081,22 +2518,16 @@ convert_all_function_calls (struct nesting_info *root)
       FOR_EACH_NEST_INFO (n, root)
        {
          tree decl = n->context;
-         bool old_no_static_chain = DECL_NO_STATIC_CHAIN (decl);
-
          walk_function (convert_tramp_reference_stmt,
                         convert_tramp_reference_op, n);
          walk_function (convert_gimple_call, NULL, n);
-
-         /* If a call to another function created the use of a chain
-            within this function, we'll have to continue iteration.  */
-         if (old_no_static_chain && !DECL_NO_STATIC_CHAIN (decl))
-           any_changed = true;
+         chain_count += DECL_STATIC_CHAIN (decl);
        }
     }
-  while (any_changed);
+  while (chain_count != old_chain_count);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "convert_all_function_calls iterations: %d\n\n",
+    fprintf (dump_file, "convert_all_function_calls iterations: %u\n\n",
             iter_count);
 }
 
@@ -2112,7 +2543,7 @@ static tree
 nesting_copy_decl (tree decl, copy_body_data *id)
 {
   struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id;
-  void **slot = pointer_map_contains (nid->root->var_map, decl);
+  tree *slot = nid->root->var_map->get (decl);
 
   if (slot)
     return (tree) *slot;
@@ -2141,15 +2572,14 @@ contains_remapped_vars (tree *tp, int *walk_subtrees, void *data)
 {
   struct nesting_info *root = (struct nesting_info *) data;
   tree t = *tp;
-  void **slot;
 
   if (DECL_P (t))
     {
       *walk_subtrees = 0;
-      slot = pointer_map_contains (root->var_map, t);
+      tree *slot = root->var_map->get (t);
 
       if (slot)
-       return (tree) *slot;
+       return *slot;
     }
   return NULL;
 }
@@ -2168,39 +2598,46 @@ remap_vla_decls (tree block, struct nesting_info *root)
        subblock = BLOCK_CHAIN (subblock))
     remap_vla_decls (subblock, root);
 
-  for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
-    {
-      if (TREE_CODE (var) == VAR_DECL
-         && variably_modified_type_p (TREE_TYPE (var), NULL)
-         && DECL_HAS_VALUE_EXPR_P (var))
-       {
-         type = TREE_TYPE (var);
-         val = DECL_VALUE_EXPR (var);
-         if (walk_tree (&type, contains_remapped_vars, root, NULL) != NULL
-             ||  walk_tree (&val, contains_remapped_vars, root, NULL) != NULL)
-           break;
-       }
-    }
+  for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
+    if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
+      {
+       val = DECL_VALUE_EXPR (var);
+       type = TREE_TYPE (var);
+
+       if (!(TREE_CODE (val) == INDIRECT_REF
+             && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
+             && variably_modified_type_p (type, NULL)))
+         continue;
+
+       if (root->var_map->get (TREE_OPERAND (val, 0))
+           || walk_tree (&type, contains_remapped_vars, root, NULL))
+         break;
+      }
+
   if (var == NULL_TREE)
     return;
 
   memset (&id, 0, sizeof (id));
   id.cb.copy_decl = nesting_copy_decl;
-  id.cb.decl_map = pointer_map_create ();
+  id.cb.decl_map = new hash_map<tree, tree>;
   id.root = root;
 
-  for (; var; var = TREE_CHAIN (var))
-    if (TREE_CODE (var) == VAR_DECL
-       && variably_modified_type_p (TREE_TYPE (var), NULL)
-       && DECL_HAS_VALUE_EXPR_P (var))
+  for (; var; var = DECL_CHAIN (var))
+    if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
       {
        struct nesting_info *i;
-       tree newt, t, context;
+       tree newt, context;
 
-       t = type = TREE_TYPE (var);
        val = DECL_VALUE_EXPR (var);
-       if (walk_tree (&type, contains_remapped_vars, root, NULL) == NULL
-           && walk_tree (&val, contains_remapped_vars, root, NULL) == NULL)
+       type = TREE_TYPE (var);
+
+       if (!(TREE_CODE (val) == INDIRECT_REF
+             && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
+             && variably_modified_type_p (type, NULL)))
+         continue;
+
+       tree *slot = root->var_map->get (TREE_OPERAND (val, 0));
+       if (!slot && !walk_tree (&type, contains_remapped_vars, root, NULL))
          continue;
 
        context = decl_function_context (var);
@@ -2211,6 +2648,15 @@ remap_vla_decls (tree block, struct nesting_info *root)
        if (i == NULL)
          continue;
 
+       /* Fully expand value expressions.  This avoids having debug variables
+          only referenced from them and that can be swept during GC.  */
+        if (slot)
+         {
+           tree t = (tree) *slot;
+           gcc_assert (DECL_P (t) && DECL_HAS_VALUE_EXPR_P (t));
+           val = build1 (INDIRECT_REF, TREE_TYPE (val), DECL_VALUE_EXPR (t));
+         }
+
        id.cb.src_fn = i->context;
        id.cb.dst_fn = i->context;
        id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
@@ -2219,13 +2665,13 @@ remap_vla_decls (tree block, struct nesting_info *root)
        while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
          {
            newt = TREE_TYPE (newt);
-           t = TREE_TYPE (t);
+           type = TREE_TYPE (type);
          }
        if (TYPE_NAME (newt)
            && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
            && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
-           && newt != t
-           && TYPE_NAME (newt) == TYPE_NAME (t))
+           && newt != type
+           && TYPE_NAME (newt) == TYPE_NAME (type))
          TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
 
        walk_tree (&val, copy_tree_body_r, &id.cb, NULL);
@@ -2233,7 +2679,16 @@ remap_vla_decls (tree block, struct nesting_info *root)
          SET_DECL_VALUE_EXPR (var, val);
       }
 
-  pointer_map_destroy (id.cb.decl_map);
+  delete id.cb.decl_map;
+}
+
+/* Fold the MEM_REF *E.  */
+bool
+fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
+{
+  tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
+  *ref_p = fold (*ref_p);
+  return true;
 }
 
 /* Do "everything else" to clean up or complete state collected by the
@@ -2271,22 +2726,22 @@ finalize_nesting_tree_1 (struct nesting_info *root)
         expression get substituted in instantiate_virtual_regs().  */
       for (adjust = &root->new_local_var_chain;
           *adjust != root->frame_decl;
-          adjust = &TREE_CHAIN (*adjust))
-       gcc_assert (TREE_CHAIN (*adjust));
-      *adjust = TREE_CHAIN (*adjust);
+          adjust = &DECL_CHAIN (*adjust))
+       gcc_assert (DECL_CHAIN (*adjust));
+      *adjust = DECL_CHAIN (*adjust);
 
-      TREE_CHAIN (root->frame_decl) = NULL_TREE;
+      DECL_CHAIN (root->frame_decl) = NULL_TREE;
       declare_vars (root->frame_decl,
                    gimple_seq_first_stmt (gimple_body (context)), true);
     }
 
-  /* If any parameters were referenced non-locally, then we need to 
+  /* If any parameters were referenced non-locally, then we need to
      insert a copy.  Likewise, if any variables were referenced by
      pointer, we need to initialize the address.  */
   if (root->any_parm_remapped)
     {
       tree p;
-      for (p = DECL_ARGUMENTS (context); p ; p = TREE_CHAIN (p))
+      for (p = DECL_ARGUMENTS (context); p ; p = DECL_CHAIN (p))
        {
          tree field, x, y;
 
@@ -2299,10 +2754,6 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          else
            x = p;
 
-         y = build3 (COMPONENT_REF, TREE_TYPE (field),
-                     root->frame_decl, field, NULL_TREE);
-         stmt = gimple_build_assign (y, x);
-         gimple_seq_add_stmt (&stmt_list, stmt);
          /* If the assignment is from a non-register the stmt is
             not valid gimple.  Make it so by using a temporary instead.  */
          if (!is_gimple_reg (x)
@@ -2310,8 +2761,12 @@ finalize_nesting_tree_1 (struct nesting_info *root)
            {
              gimple_stmt_iterator gsi = gsi_last (stmt_list);
              x = init_tmp_var (root, x, &gsi);
-             gimple_assign_set_rhs1 (stmt, x);
            }
+
+         y = build3 (COMPONENT_REF, TREE_TYPE (field),
+                     root->frame_decl, field, NULL_TREE);
+         stmt = gimple_build_assign (y, x);
+         gimple_seq_add_stmt (&stmt_list, stmt);
        }
     }
 
@@ -2337,7 +2792,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          if (!field)
            continue;
 
-         gcc_assert (!DECL_NO_STATIC_CHAIN (i->context));
+         gcc_assert (DECL_STATIC_CHAIN (i->context));
          arg3 = build_addr (root->frame_decl, context);
 
          arg2 = build_addr (i->context, context);
@@ -2346,7 +2801,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
                      root->frame_decl, field, NULL_TREE);
          arg1 = build_addr (x, context);
 
-         x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
+         x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
          stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
          gimple_seq_add_stmt (&stmt_list, stmt);
        }
@@ -2355,9 +2810,9 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   /* If we created initialization statements, insert them.  */
   if (stmt_list)
     {
-      gimple bind;
+      gbind *bind;
       annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context));
-      bind = gimple_seq_first_stmt (gimple_body (context));
+      bind = gimple_seq_first_stmt_as_a_bind (gimple_body (context));
       gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind));
       gimple_bind_set_body (bind, stmt_list);
     }
@@ -2386,12 +2841,12 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   if (root->debug_var_chain)
     {
       tree debug_var;
-      gimple scope;
+      gbind *scope;
 
       remap_vla_decls (DECL_INITIAL (root->context), root);
 
       for (debug_var = root->debug_var_chain; debug_var;
-          debug_var = TREE_CHAIN (debug_var))
+          debug_var = DECL_CHAIN (debug_var))
        if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
          break;
 
@@ -2403,10 +2858,10 @@ finalize_nesting_tree_1 (struct nesting_info *root)
 
          memset (&id, 0, sizeof (id));
          id.cb.copy_decl = nesting_copy_decl;
-         id.cb.decl_map = pointer_map_create ();
+         id.cb.decl_map = new hash_map<tree, tree>;
          id.root = root;
 
-         for (; debug_var; debug_var = TREE_CHAIN (debug_var))
+         for (; debug_var; debug_var = DECL_CHAIN (debug_var))
            if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
              {
                tree type = TREE_TYPE (debug_var);
@@ -2438,10 +2893,10 @@ finalize_nesting_tree_1 (struct nesting_info *root)
                  TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
              }
 
-         pointer_map_destroy (id.cb.decl_map);
+         delete id.cb.decl_map;
        }
 
-      scope = gimple_seq_first_stmt (gimple_body (root->context));
+      scope = gimple_seq_first_stmt_as_a_bind (gimple_body (root->context));
       if (gimple_bind_block (scope))
        declare_vars (root->debug_var_chain, scope, true);
       else
@@ -2450,6 +2905,9 @@ finalize_nesting_tree_1 (struct nesting_info *root)
                     root->debug_var_chain);
     }
 
+  /* Fold the rewritten MEM_REF trees.  */
+  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
+
   /* Dump the translated tree function.  */
   if (dump_file)
     {
@@ -2471,14 +2929,14 @@ finalize_nesting_tree (struct nesting_info *root)
 static void
 unnest_nesting_tree_1 (struct nesting_info *root)
 {
-  struct cgraph_node *node = cgraph_node (root->context);
+  struct cgraph_node *node = cgraph_node::get (root->context);
 
   /* For nested functions update the cgraph to reflect unnesting.
      We also delay finalizing of these functions up to this point.  */
   if (node->origin)
     {
-       cgraph_unnest_node (cgraph_node (root->context));
-       cgraph_finalize_function (root->context, true);
+       node->unnest ();
+       cgraph_node::finalize_function (root->context, true);
     }
 }
 
@@ -2501,8 +2959,9 @@ free_nesting_tree (struct nesting_info *root)
   do
     {
       next = iter_nestinfo_next (node);
-      pointer_map_destroy (node->var_map);
-      pointer_map_destroy (node->field_map);
+      delete node->var_map;
+      delete node->field_map;
+      delete node->mem_refs;
       free (node);
       node = next;
     }
@@ -2528,13 +2987,9 @@ lower_nested_functions (tree fndecl)
 {
   struct cgraph_node *cgn;
   struct nesting_info *root;
-#ifdef ENABLE_CHECKING
-  struct nesting_info *n;
-  bitmap orig_decl_no_static_chain;
-#endif
 
   /* If there are no nested functions, there's nothing to do.  */
-  cgn = cgraph_node (fndecl);
+  cgn = cgraph_node::get (fndecl);
   if (!cgn->nested)
     return;
 
@@ -2548,15 +3003,6 @@ lower_nested_functions (tree fndecl)
   bitmap_obstack_initialize (&nesting_info_bitmap_obstack);
   root = create_nesting_tree (cgn);
 
-#ifdef ENABLE_CHECKING
-  /* The C++ and Ada front ends set DECL_NO_STATIC_CHAIN in various
-     instances where they expect no static chain needed.  */
-  orig_decl_no_static_chain = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
-  FOR_EACH_NEST_INFO (n, root)
-    if (DECL_NO_STATIC_CHAIN (n->context))
-      bitmap_set_bit (orig_decl_no_static_chain, DECL_UID (n->context));
-#endif
-
   walk_all_functions (convert_nonlocal_reference_stmt,
                       convert_nonlocal_reference_op,
                      root);
@@ -2570,13 +3016,6 @@ lower_nested_functions (tree fndecl)
   finalize_nesting_tree (root);
   unnest_nesting_tree (root);
 
-#ifdef ENABLE_CHECKING
-  /* Validate the original settings of DECL_NO_STATIC_CHAIN.  */
-  FOR_EACH_NEST_INFO (n, root)
-    if (bitmap_bit_p (orig_decl_no_static_chain, DECL_UID (n->context)))
-      gcc_assert (DECL_NO_STATIC_CHAIN (n->context));
-#endif
-
   free_nesting_tree (root);
   bitmap_obstack_release (&nesting_info_bitmap_obstack);