[Ada] Various typo fixes and reformatting of comments
[platform/upstream/gcc.git] / gcc / tree-nested.c
index 4c8eda9..de168df 100644 (file)
@@ -1,5 +1,5 @@
 /* Nested function decomposition for GIMPLE.
-   Copyright (C) 2004-2018 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -104,6 +104,7 @@ struct nesting_info
   tree chain_decl;
   tree nl_goto_field;
 
+  bool thunk_p;
   bool any_parm_remapped;
   bool any_tramp_created;
   bool any_descr_created;
@@ -159,15 +160,22 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
   DECL_CONTEXT (tmp_var) = info->context;
   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)
-    DECL_GIMPLE_REG_P (tmp_var) = 1;
 
   info->new_local_var_chain = tmp_var;
 
   return tmp_var;
 }
 
+/* Like build_simple_mem_ref, but set TREE_THIS_NOTRAP on the result.  */
+
+static tree
+build_simple_mem_ref_notrap (tree ptr)
+{
+  tree t = build_simple_mem_ref (ptr);
+  TREE_THIS_NOTRAP (t) = 1;
+  return t;
+}
+
 /* Take the address of EXP to be used within function CONTEXT.
    Mark it for addressability as necessary.  */
 
@@ -834,6 +842,7 @@ create_nesting_tree (struct cgraph_node *cgn)
   info->mem_refs = new hash_set<tree *>;
   info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
   info->context = cgn->decl;
+  info->thunk_p = cgn->thunk.thunk_p;
 
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
     {
@@ -875,7 +884,7 @@ get_static_chain (struct nesting_info *info, tree target_context,
        {
          tree field = get_chain_field (i);
 
-         x = build_simple_mem_ref (x);
+         x = build_simple_mem_ref_notrap (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, gsi);
        }
@@ -912,12 +921,12 @@ get_frame_field (struct nesting_info *info, tree target_context,
        {
          tree field = get_chain_field (i);
 
-         x = build_simple_mem_ref (x);
+         x = build_simple_mem_ref_notrap (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, gsi);
        }
 
-      x = build_simple_mem_ref (x);
+      x = build_simple_mem_ref_notrap (x);
     }
 
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
@@ -961,16 +970,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 = build_simple_mem_ref (x);
+         x = build_simple_mem_ref_notrap (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
        }
-      x = build_simple_mem_ref (x);
+      x = build_simple_mem_ref_notrap (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 = build_simple_mem_ref (x);
+    x = build_simple_mem_ref_notrap (x);
 
   /* ??? We should be remapping types as well, surely.  */
   new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
@@ -1058,7 +1067,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 = build_simple_mem_ref (x);
+               x = build_simple_mem_ref_notrap (x);
              }
          }
 
@@ -1176,7 +1185,7 @@ 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;
-  tree clause, decl;
+  tree clause, decl, *pdecl;
   int dummy;
   bitmap new_suppress;
 
@@ -1185,11 +1194,23 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 
   for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
     {
+      pdecl = NULL;
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            need_stmts = true;
+         if (TREE_CODE (OMP_CLAUSE_DECL (clause)) == MEM_REF)
+           {
+             pdecl = &TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0);
+             if (TREE_CODE (*pdecl) == POINTER_PLUS_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+             if (TREE_CODE (*pdecl) == INDIRECT_REF
+                 || TREE_CODE (*pdecl) == ADDR_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+           }
          goto do_decl_clause;
 
        case OMP_CLAUSE_LASTPRIVATE:
@@ -1213,9 +1234,12 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_TO_DECLARE:
        case OMP_CLAUSE_LINK:
        case OMP_CLAUSE_USE_DEVICE_PTR:
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
        case OMP_CLAUSE_IS_DEVICE_PTR:
        do_decl_clause:
-         decl = OMP_CLAUSE_DECL (clause);
+         if (pdecl == NULL)
+           pdecl = &OMP_CLAUSE_DECL (clause);
+         decl = *pdecl;
          if (VAR_P (decl)
              && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
            break;
@@ -1224,7 +1248,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
              if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_SHARED)
                OMP_CLAUSE_SHARED_READONLY (clause) = 0;
              bitmap_set_bit (new_suppress, DECL_UID (decl));
-             OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
+             *pdecl = get_nonlocal_debug_decl (info, decl);
              if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
                need_chain = true;
            }
@@ -1312,6 +1336,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
              convert_nonlocal_reference_op
                (&OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), &dummy, wi);
            }
+         /* FALLTHRU */
+       case OMP_CLAUSE_NONTEMPORAL:
          /* Like do_decl_clause, but don't add any suppression.  */
          decl = OMP_CLAUSE_DECL (clause);
          if (VAR_P (decl)
@@ -1320,8 +1346,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          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;
+             need_chain = true;
            }
          break;
 
@@ -1338,11 +1363,14 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_THREADS:
        case OMP_CLAUSE_SIMD:
        case OMP_CLAUSE_DEFAULTMAP:
+       case OMP_CLAUSE_ORDER:
        case OMP_CLAUSE_SEQ:
        case OMP_CLAUSE_INDEPENDENT:
        case OMP_CLAUSE_AUTO:
        case OMP_CLAUSE_IF_PRESENT:
        case OMP_CLAUSE_FINALIZE:
+       case OMP_CLAUSE__CONDTEMP_:
+       case OMP_CLAUSE__SCANTEMP_:
          break;
 
          /* The following clause belongs to the OpenACC cache directive, which
@@ -1363,8 +1391,10 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          /* The following clauses are only added during OMP lowering; nested
             function decomposition happens before that.  */
        case OMP_CLAUSE__LOOPTEMP_:
+       case OMP_CLAUSE__REDUCTEMP_:
        case OMP_CLAUSE__SIMDUID_:
        case OMP_CLAUSE__GRIDDIM_:
+       case OMP_CLAUSE__SIMT_:
          /* Anything else.  */
        default:
          gcc_unreachable ();
@@ -1378,6 +1408,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            {
              tree old_context
@@ -1488,6 +1520,20 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        }
       break;
 
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         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;
+       }
+      /* FALLTHRU */
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_suppress = info->suppress_expansion;
@@ -1544,6 +1590,14 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->suppress_expansion = save_suppress;
       break;
 
+    case GIMPLE_OMP_TASKGROUP:
+      save_suppress = info->suppress_expansion;
+      convert_nonlocal_omp_clauses (gimple_omp_taskgroup_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_TARGET:
       if (!is_gimple_omp_offloaded (stmt))
        {
@@ -1584,18 +1638,10 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       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:
+    case GIMPLE_OMP_SCAN:
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       break;
@@ -1632,6 +1678,21 @@ convert_nonlocal_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 (DECL_P (lhs)
+             && !(TREE_STATIC (lhs) || DECL_EXTERNAL (lhs))
+             && decl_function_context (lhs) != info->context)
+           {
+             gsi_replace (gsi, gimple_build_nop (), true);
+             break;
+           }
+       }
+      *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.  */
@@ -1857,7 +1918,7 @@ 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;
-  tree clause, decl;
+  tree clause, decl, *pdecl;
   int dummy;
   bitmap new_suppress;
 
@@ -1866,11 +1927,23 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 
   for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
     {
+      pdecl = NULL;
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            need_stmts = true;
+         if (TREE_CODE (OMP_CLAUSE_DECL (clause)) == MEM_REF)
+           {
+             pdecl = &TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0);
+             if (TREE_CODE (*pdecl) == POINTER_PLUS_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+             if (TREE_CODE (*pdecl) == INDIRECT_REF
+                 || TREE_CODE (*pdecl) == ADDR_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+           }
          goto do_decl_clause;
 
        case OMP_CLAUSE_LASTPRIVATE:
@@ -1894,9 +1967,12 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_TO_DECLARE:
        case OMP_CLAUSE_LINK:
        case OMP_CLAUSE_USE_DEVICE_PTR:
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
        case OMP_CLAUSE_IS_DEVICE_PTR:
        do_decl_clause:
-         decl = OMP_CLAUSE_DECL (clause);
+         if (pdecl == NULL)
+           pdecl = &OMP_CLAUSE_DECL (clause);
+         decl = *pdecl;
          if (VAR_P (decl)
              && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
            break;
@@ -1909,8 +1985,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                  if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_SHARED)
                    OMP_CLAUSE_SHARED_READONLY (clause) = 0;
                  bitmap_set_bit (new_suppress, DECL_UID (decl));
-                 OMP_CLAUSE_DECL (clause)
-                   = get_local_debug_decl (info, decl, field);
+                 *pdecl = get_local_debug_decl (info, decl, field);
                  need_frame = true;
                }
            }
@@ -1998,6 +2073,8 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
              convert_local_reference_op
                (&OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), &dummy, wi);
            }
+         /* FALLTHRU */
+       case OMP_CLAUSE_NONTEMPORAL:
          /* Like do_decl_clause, but don't add any suppression.  */
          decl = OMP_CLAUSE_DECL (clause);
          if (VAR_P (decl)
@@ -2029,11 +2106,14 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_THREADS:
        case OMP_CLAUSE_SIMD:
        case OMP_CLAUSE_DEFAULTMAP:
+       case OMP_CLAUSE_ORDER:
        case OMP_CLAUSE_SEQ:
        case OMP_CLAUSE_INDEPENDENT:
        case OMP_CLAUSE_AUTO:
        case OMP_CLAUSE_IF_PRESENT:
        case OMP_CLAUSE_FINALIZE:
+       case OMP_CLAUSE__CONDTEMP_:
+       case OMP_CLAUSE__SCANTEMP_:
          break;
 
          /* The following clause belongs to the OpenACC cache directive, which
@@ -2054,8 +2134,10 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          /* The following clauses are only added during OMP lowering; nested
             function decomposition happens before that.  */
        case OMP_CLAUSE__LOOPTEMP_:
+       case OMP_CLAUSE__REDUCTEMP_:
        case OMP_CLAUSE__SIMDUID_:
        case OMP_CLAUSE__GRIDDIM_:
+       case OMP_CLAUSE__SIMT_:
          /* Anything else.  */
        default:
          gcc_unreachable ();
@@ -2069,6 +2151,8 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            {
              tree old_context
@@ -2129,6 +2213,18 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
   switch (gimple_code (stmt))
     {
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         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;
+       }
+      /* FALLTHRU */
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_suppress = info->suppress_expansion;
@@ -2199,6 +2295,14 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->suppress_expansion = save_suppress;
       break;
 
+    case GIMPLE_OMP_TASKGROUP:
+      save_suppress = info->suppress_expansion;
+      convert_local_omp_clauses (gimple_omp_taskgroup_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_TARGET:
       if (!is_gimple_omp_offloaded (stmt))
        {
@@ -2252,18 +2356,10 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->static_chain_added |= save_static_chain_added;
       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:
+    case GIMPLE_OMP_SCAN:
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       break;
@@ -2278,7 +2374,8 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       if (gimple_clobber_p (stmt))
        {
          tree lhs = gimple_assign_lhs (stmt);
-         if (!use_pointer_in_frame (lhs)
+         if (DECL_P (lhs)
+             && !use_pointer_in_frame (lhs)
              && lookup_field_for_decl (info, lhs, NO_INSERT))
            {
              gsi_replace (gsi, gimple_build_nop (), true);
@@ -2560,6 +2657,14 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        break;
       }
 
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         *handled_ops_p = false;
+         return NULL_TREE;
+       }
+      goto do_parallel;
+
     case GIMPLE_OMP_TARGET:
       if (!is_gimple_omp_offloaded (stmt))
        {
@@ -2569,6 +2674,7 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       /* FALLTHRU */
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
+    do_parallel:
       {
        tree save_local_var_chain = info->new_local_var_chain;
         walk_gimple_op (stmt, convert_tramp_reference_op, wi);
@@ -2676,6 +2782,15 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        }
       break;
 
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         walk_body (convert_gimple_call, NULL, info,
+                    gimple_omp_body_ptr (stmt));
+         break;
+       }
+      /* FALLTHRU */
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_static_chain_added = info->static_chain_added;
@@ -2751,10 +2866,10 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     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_SCAN:
     case GIMPLE_OMP_CRITICAL:
       walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       break;
@@ -2786,6 +2901,8 @@ convert_all_function_calls (struct nesting_info *root)
      within the debugger.  */
   FOR_EACH_NEST_INFO (n, root)
     {
+      if (n->thunk_p)
+       continue;
       tree decl = n->context;
       if (!optimize)
        {
@@ -2806,6 +2923,14 @@ convert_all_function_calls (struct nesting_info *root)
       chain_count += DECL_STATIC_CHAIN (decl);
     }
 
+  FOR_EACH_NEST_INFO (n, root)
+    if (n->thunk_p)
+      {
+       tree decl = n->context;
+       tree alias = cgraph_node::get (decl)->thunk.alias;
+       DECL_STATIC_CHAIN (decl) = DECL_STATIC_CHAIN (alias);
+      }
+
   /* 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.  */
@@ -2825,12 +2950,22 @@ convert_all_function_calls (struct nesting_info *root)
 
       FOR_EACH_NEST_INFO (n, root)
        {
+         if (n->thunk_p)
+           continue;
          tree decl = n->context;
          walk_function (convert_tramp_reference_stmt,
                         convert_tramp_reference_op, n);
          walk_function (convert_gimple_call, NULL, n);
          chain_count += DECL_STATIC_CHAIN (decl);
        }
+
+      FOR_EACH_NEST_INFO (n, root)
+       if (n->thunk_p)
+         {
+           tree decl = n->context;
+           tree alias = cgraph_node::get (decl)->thunk.alias;
+           DECL_STATIC_CHAIN (decl) = DECL_STATIC_CHAIN (alias);
+         }
     }
   while (chain_count != old_chain_count);
 
@@ -3055,12 +3190,13 @@ build_init_call_stmt (struct nesting_info *info, tree decl, tree field,
 static void
 finalize_nesting_tree_1 (struct nesting_info *root)
 {
-  gimple_seq stmt_list;
+  gimple_seq stmt_list = NULL;
   gimple *stmt;
   tree context = root->context;
   struct function *sf;
 
-  stmt_list = NULL;
+  if (root->thunk_p)
+    return;
 
   /* If we created a non-local frame type or decl, we need to lay them
      out at this time.  */
@@ -3340,7 +3476,8 @@ unnest_nesting_tree_1 (struct nesting_info *root)
   if (node->origin)
     {
        node->unnest ();
-       cgraph_node::finalize_function (root->context, true);
+       if (!root->thunk_p)
+        cgraph_node::finalize_function (root->context, true);
     }
 }
 
@@ -3380,7 +3517,8 @@ gimplify_all_functions (struct cgraph_node *root)
   if (!gimple_body (root->decl))
     gimplify_function_tree (root->decl);
   for (iter = root->nested; iter; iter = iter->next_nested)
-    gimplify_all_functions (iter);
+    if (!iter->thunk.thunk_p)
+      gimplify_all_functions (iter);
 }
 
 /* Main entry point for this pass.  Process FNDECL and all of its nested