]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/tree-nested.c
tree-core.h: Include symtab.h.
[gcc.git] / gcc / tree-nested.c
index fb95088b64805e9f3ca4edf5a781ab3b31004448..6b750208dfdb9ceef5183a80471535ee43226033 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 "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
 #include "tree.h"
+#include "gimple.h"
 #include "rtl.h"
+#include "alias.h"
+#include "fold-const.h"
+#include "stringpool.h"
+#include "stor-layout.h"
 #include "tm_p.h"
-#include "function.h"
 #include "tree-dump.h"
 #include "tree-inline.h"
-#include "gimple.h"
+#include "internal-fn.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
 #include "tree-iterator.h"
-#include "tree-flow.h"
 #include "cgraph.h"
-#include "expr.h"
+#include "tree-cfg.h"
+#include "flags.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
@@ -84,8 +99,9 @@ struct nesting_info
   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 +165,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 +201,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 +215,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 +252,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 +292,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 +328,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
@@ -400,7 +415,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;
 
@@ -487,7 +502,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 +525,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,7 +545,7 @@ 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
@@ -562,7 +575,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 +591,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 +612,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 +629,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 +660,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));
@@ -694,16 +708,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 +732,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 +776,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 +811,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);
@@ -812,7 +828,7 @@ 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.  */
+   and in OMP lowering.  */
 
 static tree
 get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
@@ -820,12 +836,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 +858,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 +890,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 +944,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 +1026,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);
@@ -1053,7 +1061,9 @@ static bool
 convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 {
   struct nesting_info *const info = (struct nesting_info *) wi->info;
-  bool need_chain = false, need_stmts = false;
+  /* If not optimizing, we will force the creation of the CHAIN object in
+     convert_all_function_calls, so we need to take it into account here.  */
+  bool need_chain = info->outer && !optimize, need_stmts = false;
   tree clause, decl;
   int dummy;
   bitmap new_suppress;
@@ -1075,6 +1085,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 +1107,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 +1116,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 +1186,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 +1210,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 +1222,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 +1285,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 +1341,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 +1354,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 +1366,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,24 +1374,94 @@ 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;
@@ -1328,18 +1483,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);
@@ -1366,7 +1520,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.  */
@@ -1486,19 +1640,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
@@ -1529,7 +1691,9 @@ static bool
 convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 {
   struct nesting_info *const info = (struct nesting_info *) wi->info;
-  bool need_frame = false, need_stmts = false;
+  /* If not optimizing, we will force the creation of the FRAME object in
+     convert_all_function_calls, so we need to take it into account here.  */
+  bool need_frame = info->inner && !optimize, need_stmts = false;
   tree clause, decl;
   int dummy;
   bitmap new_suppress;
@@ -1551,6 +1715,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:
@@ -1578,20 +1751,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:
@@ -1614,10 +1850,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;
            }
@@ -1626,7 +1862,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:
@@ -1671,7 +1913,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,
@@ -1683,10 +1925,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;
 
@@ -1694,7 +1937,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;
 
@@ -1702,15 +1945,60 @@ 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:
@@ -1719,6 +2007,52 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       *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.  */
@@ -1742,8 +2076,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)
@@ -1776,7 +2109,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);
@@ -1784,16 +2117,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;
@@ -1814,10 +2147,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;
@@ -1825,7 +2157,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;
@@ -1861,7 +2193,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))
@@ -1904,7 +2236,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);
 
@@ -1934,6 +2266,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))
@@ -1946,16 +2279,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;
 }
 
@@ -1986,8 +2342,9 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       target_context = decl_function_context (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;
@@ -1996,7 +2353,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;
@@ -2024,17 +2381,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:
@@ -2054,16 +2449,25 @@ 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 clear static_chain for all decls that haven't
-     used the static chain already for variable access.  */
+     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)
+       {
+         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))
@@ -2072,6 +2476,7 @@ convert_all_function_calls (struct nesting_info *root)
        }
       else
        DECL_STATIC_CHAIN (decl) = 1;
+      chain_count += DECL_STATIC_CHAIN (decl);
     }
 
   /* Walk the functions and perform transformations.  Note that these
@@ -2084,7 +2489,8 @@ convert_all_function_calls (struct nesting_info *root)
   iter_count = 0;
   do
     {
-      any_changed = false;
+      old_chain_count = chain_count;
+      chain_count = 0;
       iter_count++;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2093,22 +2499,16 @@ convert_all_function_calls (struct nesting_info *root)
       FOR_EACH_NEST_INFO (n, root)
        {
          tree decl = n->context;
-         bool old_static_chain = DECL_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_static_chain && DECL_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);
 }
 
@@ -2124,7 +2524,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;
@@ -2153,15 +2553,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;
 }
@@ -2180,39 +2579,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);
@@ -2223,6 +2629,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);
@@ -2231,13 +2646,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);
@@ -2245,7 +2660,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
@@ -2283,11 +2707,11 @@ 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);
     }
@@ -2298,7 +2722,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   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;
 
@@ -2311,10 +2735,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)
@@ -2322,8 +2742,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);
        }
     }
 
@@ -2358,7 +2782,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);
        }
@@ -2367,9 +2791,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);
     }
@@ -2398,12 +2822,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;
 
@@ -2415,10 +2839,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);
@@ -2450,10 +2874,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
@@ -2462,6 +2886,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)
     {
@@ -2483,14 +2910,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);
     }
 }
 
@@ -2513,8 +2940,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;
     }
@@ -2542,7 +2970,7 @@ lower_nested_functions (tree fndecl)
   struct nesting_info *root;
 
   /* If there are no nested functions, there's nothing to do.  */
-  cgn = cgraph_node (fndecl);
+  cgn = cgraph_node::get (fndecl);
   if (!cgn->nested)
     return;
 
This page took 0.079969 seconds and 5 git commands to generate.