diff mbox

[v2] Destroy arguments for _Cilk_spawn calling in the child (PR 80038)

Message ID 1493436025.969.10.camel@stu.xidian.edu.cn
State New
Headers show

Commit Message

Xi Ruoyao April 29, 2017, 3:20 a.m. UTC
On 2017-04-28 08:42 -0600, Jeff Law wrote:
> On 04/28/2017 08:31 AM, Xi Ruoyao wrote:
> > Should I prepare (re-diff) a patch for current trunk?
> If you want for the trunk, yes.

Rediff for current GCC trunk.

Comments

Jeff Law May 1, 2017, 10:26 p.m. UTC | #1
On 04/28/2017 09:20 PM, Xi Ruoyao wrote:
> On 2017-04-28 08:42 -0600, Jeff Law wrote:
>> On 04/28/2017 08:31 AM, Xi Ruoyao wrote:
>>> Should I prepare (re-diff) a patch for current trunk?
>> If you want for the trunk, yes.
> Rediff for current GCC trunk.
> -- Xi Ruoyao <ryxi@stu.xidian.edu.cn> School of Aerospace Science and 
> Technology, Xidian University
> 
> 
> pr80038-v2.patch
> 
> 
>  From aa16cfe3b8f949abc0bb2da4e09f7f61bd01a05d Mon Sep 17 00:00:00 2001
> From: Xi Ruoyao<xry111@stu.xidian.edu.cn>
> Date: Fri, 24 Mar 2017 04:35:23 +0800
> Subject: [PATCH] Destroy temps for _Cilk_spawn calling in the child (PR
>   c++/80038)
> 
> Revert r227423, and re-fix PR60586 without breaking cilk specs.
> 
> 2017-03-24  Xi Ruoyao<ryxi@stu.xidian.edu.cn>
> 
> 	PR c++/80038
> 	* c-family/c-common.h (cilk_gimplify_call_params_in_spawned_fn,
> 	  cilk_install_body_pedigree_operations): Remove prototypes.
> 	* c-family/c-gimplify.c (c_gimplify_expr): Remove the calls to
> 	  the function cilk_gimplify_call_params_in_spawned_fn.
> 	* c-family/cilk.c: (cilk_set_spawn_marker): Mark the function
> 	  calls which should be detached.
> 	  (cilk_gimplify_call_params_in_spawned_fn,
> 	   cilk_install_body_pedigree_operations): Remove function.
> 	  (gimplify_cilk_spawn): Add EXPR_STMT and CLEANUP_POINT_EXPR
> 	  unwrapping.
> 	* c/c-typeck.c (cilk_install_body_with_frame_cleanup):
> 	  Don't add pedigree operation and detach call here.
> 	* cp/cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Ditto.
> 	* cp/cp-gimplify.c (cilk_cp_gimplify_call_params_in_spawned_fn):
> 	  Remove function.
> 	  (cp_gimplify_expr): Remove the calls to the function
> 	  cilk_cp_gimplify_call_params_in_spawned_fn.
> 	* cp/semantics.c: Preserve the flag of function calls should
> 	  be detached.
> 	* cilk_common.c (expand_builtin_cilk_detach): Move pedigree
> 	  operations here.
> 	* gimplify.c (gimplify_cilk_detach): New static function.
> 	  (gimplify_call_expr, gimplify_modify_expr): Call it for the
> 	  function calls should be detached.
> 	* lto/lto-lang.c (lto_init): Set in_lto_p earlier.
> 	* tree-core.h: Document new macro EXPR_CILK_SPAWN.
> 	* tree.h: Add new macro EXPR_CILK_SPAWN.
> 	* testsuite/g++.dg/cilk-plus/CK/pr80038.cc: New test.
Thanks.  I fixed up the ChangeLog and installed this on the trunk.
jeff
Andreas Schwab May 2, 2017, 7:16 a.m. UTC | #2
This could be related to --enable-checking=release:

In file included from ../../gcc/c-family/c-common.h:26:0,
                 from ../../gcc/c-family/cilk.c:28:
../../gcc/c-family/cilk.c: In function 'bool cilk_set_spawn_marker(location_t, tree)':
../../gcc/tree.h:901:42: error: 'tree_check2' was not declared in this scope
                 CALL_EXPR, AGGR_INIT_EXPR)->base.u.bits.unsigned_flag)
                                          ^
../../gcc/c-family/cilk.c:113:9: note: in expansion of macro 'EXPR_CILK_SPAWN'
         EXPR_CILK_SPAWN (fcall) = 1;
         ^
../../gcc/tree.h:901:42: error: 'tree_check2' was not declared in this scope
                 CALL_EXPR, AGGR_INIT_EXPR)->base.u.bits.unsigned_flag)
                                          ^
../../gcc/c-family/cilk.c:115:9: note: in expansion of macro 'EXPR_CILK_SPAWN'
         EXPR_CILK_SPAWN (TREE_OPERAND (fcall, 1)) = 1;
         ^

Andreas.
diff mbox

Patch

From aa16cfe3b8f949abc0bb2da4e09f7f61bd01a05d Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@stu.xidian.edu.cn>
Date: Fri, 24 Mar 2017 04:35:23 +0800
Subject: [PATCH] Destroy temps for _Cilk_spawn calling in the child (PR
 c++/80038)

Revert r227423, and re-fix PR60586 without breaking cilk specs.

2017-03-24  Xi Ruoyao  <ryxi@stu.xidian.edu.cn>

	PR c++/80038
	* c-family/c-common.h (cilk_gimplify_call_params_in_spawned_fn,
	  cilk_install_body_pedigree_operations): Remove prototypes.
	* c-family/c-gimplify.c (c_gimplify_expr): Remove the calls to
	  the function cilk_gimplify_call_params_in_spawned_fn.
	* c-family/cilk.c: (cilk_set_spawn_marker): Mark the function
	  calls which should be detached.
	  (cilk_gimplify_call_params_in_spawned_fn,
	   cilk_install_body_pedigree_operations): Remove function.
	  (gimplify_cilk_spawn): Add EXPR_STMT and CLEANUP_POINT_EXPR
	  unwrapping.
	* c/c-typeck.c (cilk_install_body_with_frame_cleanup):
	  Don't add pedigree operation and detach call here.
	* cp/cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Ditto.
	* cp/cp-gimplify.c (cilk_cp_gimplify_call_params_in_spawned_fn):
	  Remove function.
	  (cp_gimplify_expr): Remove the calls to the function
	  cilk_cp_gimplify_call_params_in_spawned_fn.
	* cp/semantics.c: Preserve the flag of function calls should
	  be detached.
	* cilk_common.c (expand_builtin_cilk_detach): Move pedigree
	  operations here.
	* gimplify.c (gimplify_cilk_detach): New static function.
	  (gimplify_call_expr, gimplify_modify_expr): Call it for the
	  function calls should be detached.
	* lto/lto-lang.c (lto_init): Set in_lto_p earlier.
	* tree-core.h: Document new macro EXPR_CILK_SPAWN.
	* tree.h: Add new macro EXPR_CILK_SPAWN.
	* testsuite/g++.dg/cilk-plus/CK/pr80038.cc: New test.
---
 gcc/c-family/c-common.h                      |   2 -
 gcc/c-family/c-gimplify.c                    |  10 +--
 gcc/c-family/cilk.c                          | 102 +++------------------------
 gcc/c/c-typeck.c                             |   8 +--
 gcc/cilk-common.c                            |  49 +++++++++++++
 gcc/cp/cp-cilkplus.c                         |   6 +-
 gcc/cp/cp-gimplify.c                         |  40 ++---------
 gcc/cp/semantics.c                           |   2 +
 gcc/gimplify.c                               |  21 ++++++
 gcc/lto/lto-lang.c                           |   6 +-
 gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc |  47 ++++++++++++
 gcc/tree-core.h                              |   4 ++
 gcc/tree.h                                   |   6 ++
 13 files changed, 150 insertions(+), 153 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index b933342..138a0a6 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1463,7 +1463,6 @@  extern bool is_cilkplus_vector_p (tree);
 extern tree insert_cilk_frame (tree);
 extern void cilk_init_builtins (void);
 extern int gimplify_cilk_spawn (tree *);
-extern void cilk_gimplify_call_params_in_spawned_fn (tree *, gimple_seq *);
 extern void cilk_install_body_with_frame_cleanup (tree, tree, void *);
 extern bool cilk_detect_spawn_and_unwrap (tree *);
 extern bool cilk_set_spawn_marker (location_t, tree);
@@ -1471,7 +1470,6 @@  extern tree build_cilk_sync (void);
 extern tree build_cilk_spawn (location_t, tree);
 extern tree make_cilk_frame (tree);
 extern tree create_cilk_function_exit (tree, bool, bool);
-extern tree cilk_install_body_pedigree_operations (tree);
 extern void cilk_outline (tree, tree *, void *);
 extern bool contains_cilk_spawn_stmt (tree);
 extern tree cilk_for_number_of_iterations (tree);
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
index 57edb41..1ae75d2 100644
--- a/gcc/c-family/c-gimplify.c
+++ b/gcc/c-family/c-gimplify.c
@@ -280,10 +280,7 @@  c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 		 && cilk_detect_spawn_and_unwrap (expr_p));
 
       if (!seen_error ())
-	{
-	  cilk_gimplify_call_params_in_spawned_fn (expr_p, pre_p);
-	  return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
-	}
+        return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
       return GS_ERROR;
 
     case MODIFY_EXPR:
@@ -295,10 +292,7 @@  c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 	     original expression (MODIFY/INIT/CALL_EXPR) is processes as
 	     it is supposed to be.  */
 	  && !seen_error ())
-	{
-	  cilk_gimplify_call_params_in_spawned_fn (expr_p, pre_p);
-	  return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
-	}
+        return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
 
     default:;
     }
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
index 43478ff..e6df498 100644
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -109,6 +109,10 @@  cilk_set_spawn_marker (location_t loc, tree fcall)
   else
     {
       cfun->calls_cilk_spawn = true;
+      if (TREE_CODE (fcall) == CALL_EXPR)
+        EXPR_CILK_SPAWN (fcall) = 1;
+      else /* TREE_CODE (fcall) == TARGET_EXPR */
+        EXPR_CILK_SPAWN (TREE_OPERAND (fcall, 1)) = 1;
       return true;
     }
 }
@@ -775,37 +779,6 @@  create_cilk_wrapper (tree exp, tree *args_out)
   return fndecl;
 }
 
-/* Gimplify all the parameters for the Spawned function.  *EXPR_P can be a
-   CALL_EXPR, INIT_EXPR, MODIFY_EXPR or TARGET_EXPR.  *PRE_P and *POST_P are
-   gimple sequences from the caller of gimplify_cilk_spawn.  */
-
-void
-cilk_gimplify_call_params_in_spawned_fn (tree *expr_p, gimple_seq *pre_p)
-{
-  int ii = 0;
-  tree *fix_parm_expr = expr_p;
-
-  /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p.  */
-  while (TREE_CODE (*fix_parm_expr) == CLEANUP_POINT_EXPR
-	 || TREE_CODE (*fix_parm_expr) == EXPR_STMT)
-    *fix_parm_expr = TREE_OPERAND (*fix_parm_expr, 0);
-
-  if ((TREE_CODE (*expr_p) == INIT_EXPR)
-      || (TREE_CODE (*expr_p) == TARGET_EXPR)
-      || (TREE_CODE (*expr_p) == MODIFY_EXPR))
-    fix_parm_expr = &TREE_OPERAND (*expr_p, 1);
-
-  if (TREE_CODE (*fix_parm_expr) == CALL_EXPR)
-    {
-      /* Cilk outlining assumes GENERIC bodies, avoid leaking SSA names
-         via parameters.  */
-      for (ii = 0; ii < call_expr_nargs (*fix_parm_expr); ii++)
-	gimplify_arg (&CALL_EXPR_ARG (*fix_parm_expr, ii), pre_p,
-		      EXPR_LOCATION (*fix_parm_expr), false);
-    }
-}
-
-
 /* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple.  *SPAWN_P can be a
    CALL_EXPR, INIT_EXPR or MODIFY_EXPR.  Returns GS_OK if everything is fine,
    and GS_UNHANDLED, otherwise.  */
@@ -823,6 +796,12 @@  gimplify_cilk_spawn (tree *spawn_p)
 
   cfun->calls_cilk_spawn = 1;
   cfun->is_cilk_function = 1;
+
+  /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p.  */
+  while (TREE_CODE (expr) == CLEANUP_POINT_EXPR
+         || TREE_CODE (expr) == EXPR_STMT)
+    expr = TREE_OPERAND (expr, 0);
+
   new_args = NULL;
   function = create_cilk_wrapper (expr, &new_args);
 
@@ -889,67 +868,6 @@  make_cilk_frame (tree fn)
   return decl;
 }
 
-/* Returns a STATEMENT_LIST with all the pedigree operations required for
-   install body with frame cleanup functions.  FRAME_PTR is the pointer to
-   __cilkrts_stack_frame created by make_cilk_frame.  */
-
-tree
-cilk_install_body_pedigree_operations (tree frame_ptr)
-{
-  tree body_list = alloc_stmt_list ();
-  tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr); 
-  append_to_statement_list (enter_frame, &body_list);
-  
-  tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0);
-  tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0);
-
-  tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0);
-  tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
-  tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
-  tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
-  tree pedigree_parent_rank = cilk_dot (pedigree_parent, 
-					CILK_TI_PEDIGREE_RANK, 0);
-  tree pedigree_parent_parent = cilk_dot (pedigree_parent, 
-				     CILK_TI_PEDIGREE_PARENT, 0);
-  tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
-  tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
-  tree w_pedigree_parent = cilk_dot (worker_pedigree, 
-				     CILK_TI_PEDIGREE_PARENT, 0);
-
-  /* sf.pedigree.rank = worker->pedigree.rank.  */
-  tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
-		     w_pedigree_rank);
-  append_to_statement_list (exp1, &body_list);
-
-  /* sf.pedigree.parent = worker->pedigree.parent.  */
-  exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
-		 w_pedigree_parent);
-  append_to_statement_list (exp1, &body_list);
-
-  /* sf.call_parent->pedigree.rank = worker->pedigree.rank.  */
-  exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
-		 w_pedigree_rank);
-  append_to_statement_list (exp1, &body_list);
-
-  /* sf.call_parent->pedigree.parent = worker->pedigree.parent.  */
-  exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
-		 w_pedigree_parent);
-  append_to_statement_list (exp1, &body_list);
-
-  /* sf->worker.pedigree.rank = 0.  */
-  exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank, 
-		 build_zero_cst (uint64_type_node));
-  append_to_statement_list (exp1, &body_list);
-
-  /* sf->pedigree.parent = &sf->pedigree.  */
-  exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
-		 build1 (ADDR_EXPR,
-			 build_pointer_type (cilk_pedigree_type_decl),
-			 pedigree));
-  append_to_statement_list (exp1, &body_list);
-  return body_list;
-}
-
 /* Add a new variable, VAR to a variable list in WD->DECL_MAP.  HOW indicates
    whether the variable is previously defined, currently defined, or a variable 
    that is being written to.  */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index ff239e2..6f9909c 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -14215,14 +14215,8 @@  cilk_install_body_with_frame_cleanup (tree fndecl, tree body, void *w)
   add_local_decl (cfun, frame);
   
   DECL_SAVED_TREE (fndecl) = list;
-  tree frame_ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), 
-			   frame);
-  tree body_list = cilk_install_body_pedigree_operations (frame_ptr);
-  gcc_assert (TREE_CODE (body_list) == STATEMENT_LIST);
-  
-  tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, frame_ptr); 
-  append_to_statement_list (detach_expr, &body_list);
 
+  tree body_list = alloc_stmt_list ();
   cilk_outline (fndecl, &body, (struct wrapper_data *) w);
   body = fold_build_cleanup_point_expr (void_type_node, body);
 
diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c
index 46626b7..9cbe03f 100644
--- a/gcc/cilk-common.c
+++ b/gcc/cilk-common.c
@@ -365,11 +365,60 @@  expand_builtin_cilk_detach (tree exp)
   tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0);
   tree tail = cilk_arrow (worker, CILK_TI_WORKER_TAIL, 1);
 
+  tree faddr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, fptr);
+  tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, faddr);
+  expand_expr (enter_frame, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  tree pedigree = cilk_dot (fptr, CILK_TI_FRAME_PEDIGREE, 0);
+  tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
+  tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
+  tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
+  tree pedigree_parent_rank = cilk_dot (pedigree_parent,
+					CILK_TI_PEDIGREE_RANK, 0);
+  tree pedigree_parent_parent = cilk_dot (pedigree_parent,
+				     CILK_TI_PEDIGREE_PARENT, 0);
+  tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
+  tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
+  tree w_pedigree_parent = cilk_dot (worker_pedigree,
+				     CILK_TI_PEDIGREE_PARENT, 0);
+
   rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL);
   if (GET_CODE (wreg) != REG)
     wreg = copy_to_reg (wreg);
   rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL);
 
+  /* sf.pedigree.rank = worker->pedigree.rank.  */
+  tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
+		     w_pedigree_rank);
+  expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* sf.pedigree.parent = worker->pedigree.parent.  */
+  exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
+		 w_pedigree_parent);
+  expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* sf.call_parent->pedigree.rank = worker->pedigree.rank.  */
+  exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
+		 w_pedigree_rank);
+  expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* sf.call_parent->pedigree.parent = worker->pedigree.parent.  */
+  exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
+		 w_pedigree_parent);
+  expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* sf->worker.pedigree.rank = 0.  */
+  exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank,
+		 build_zero_cst (uint64_type_node));
+  expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* sf->pedigree.parent = &sf->pedigree.  */
+  exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
+		 build1 (ADDR_EXPR,
+			 build_pointer_type (cilk_pedigree_type_decl),
+			 pedigree));
+  expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
   /* TMP <- WORKER.TAIL
     *TMP <- PARENT
      TMP <- TMP + 1
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
index d147e7e..7c66448 100644
--- a/gcc/cp/cp-cilkplus.c
+++ b/gcc/cp/cp-cilkplus.c
@@ -223,11 +223,7 @@  cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
   location_t loc = EXPR_LOCATION (orig_body);
   tree list = alloc_stmt_list ();
   DECL_SAVED_TREE (fndecl) = list;
-  tree fptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), frame);
-  tree body = cilk_install_body_pedigree_operations (fptr);
-  gcc_assert (TREE_CODE (body) == STATEMENT_LIST);
-  tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, fptr);
-  append_to_statement_list (detach_expr, &body);
+  tree body = alloc_stmt_list ();
   cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd);
   append_to_statement_list (orig_body, &body);
   if (flag_exceptions)
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index f2c5296..de62414 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -88,25 +88,6 @@  finish_bc_block (tree *block, enum bc_t bc, tree label)
   DECL_CHAIN (label) = NULL_TREE;
 }
 
-/* This function is a wrapper for cilk_gimplify_call_params_in_spawned_fn.
-   *EXPR_P can be a CALL_EXPR, INIT_EXPR, MODIFY_EXPR, AGGR_INIT_EXPR or
-   TARGET_EXPR.  *PRE_P and *POST_P are gimple sequences from the caller
-   of gimplify_cilk_spawn.  */
-
-static void
-cilk_cp_gimplify_call_params_in_spawned_fn (tree *expr_p, gimple_seq *pre_p,
-					    gimple_seq *post_p)
-{
-  int ii = 0;
-
-  cilk_gimplify_call_params_in_spawned_fn (expr_p, pre_p);
-  if (TREE_CODE (*expr_p) == AGGR_INIT_EXPR)
-    for (ii = 0; ii < aggr_init_expr_nargs (*expr_p); ii++)
-      gimplify_expr (&AGGR_INIT_EXPR_ARG (*expr_p, ii), pre_p, post_p,
-		     is_gimple_reg, fb_rvalue);
-}
-
-
 /* Get the LABEL_EXPR to represent a break or continue statement
    in the current block scope.  BC indicates which.  */
 
@@ -647,11 +628,7 @@  cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
       if (fn_contains_cilk_spawn_p (cfun))
 	{
 	  if (cilk_cp_detect_spawn_and_unwrap (expr_p))
-	    {
-	      cilk_cp_gimplify_call_params_in_spawned_fn (expr_p,
-							  pre_p, post_p);
-	      return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
-	    }
+	    return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
 	  if (seen_error () && contains_cilk_spawn_stmt (*expr_p))
 	    return GS_ERROR;
 	}
@@ -666,10 +643,7 @@  cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 	if (fn_contains_cilk_spawn_p (cfun)
 	    && cilk_cp_detect_spawn_and_unwrap (expr_p)
 	    && !seen_error ())
-	  {
-	    cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p);
-	    return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
-	  }
+	  return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
 	/* If the back end isn't clever enough to know that the lhs and rhs
 	   types are the same, add an explicit conversion.  */
 	tree op0 = TREE_OPERAND (*expr_p, 0);
@@ -787,20 +761,14 @@  cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 		 && cilk_cp_detect_spawn_and_unwrap (expr_p));
 
       if (!seen_error ())
-	{
-	  cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p);
-	  return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
-	}
+        return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
       return GS_ERROR;
 
     case CALL_EXPR:
       if (fn_contains_cilk_spawn_p (cfun)
 	  && cilk_cp_detect_spawn_and_unwrap (expr_p)
 	  && !seen_error ())
-	{
-	  cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p);
-	  return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
-	}
+        return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
       ret = GS_OK;
       if (!CALL_EXPR_FN (*expr_p))
 	/* Internal function call.  */;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a69500..4db2462 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4103,6 +4103,8 @@  simplify_aggr_init_expr (tree *tp)
     = CALL_EXPR_OPERATOR_SYNTAX (aggr_init_expr);
   CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (aggr_init_expr);
   CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (aggr_init_expr);
+  /* Preserve CILK_SPAWN flag.  */
+  EXPR_CILK_SPAWN (call_expr) = EXPR_CILK_SPAWN (aggr_init_expr);
 
   if (style == ctor)
     {
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index c69d5b9..fd27eb1 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -3071,6 +3071,19 @@  maybe_fold_stmt (gimple_stmt_iterator *gsi)
   return fold_stmt (gsi);
 }
 
+/* Add a gimple call to __builtin_cilk_detach to GIMPLE sequence PRE_P,
+   with the pointer to the proper cilk frame.  */
+static void
+gimplify_cilk_detach (gimple_seq *pre_p)
+{
+  tree frame = cfun->cilk_frame_decl;
+  tree ptrf = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl,
+		      frame);
+  gcall *detach = gimple_build_call (cilk_detach_fndecl, 1,
+				     ptrf);
+  gimplify_seq_add_stmt(pre_p, detach);
+}
+
 /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
    WANT_VALUE is true if the result of the call is desired.  */
 
@@ -3107,6 +3120,9 @@  gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 			EXPR_LOCATION (*expr_p));
 	  vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
 	}
+
+      if (EXPR_CILK_SPAWN (*expr_p))
+        gimplify_cilk_detach (pre_p);
       gimple *call = gimple_build_call_internal_vec (ifn, vargs);
       gimplify_seq_add_stmt (pre_p, call);
       return GS_ALL_DONE;
@@ -3338,6 +3354,8 @@  gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
       call = gimple_build_call_from_tree (*expr_p);
       gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
       notice_special_calls (call);
+      if (EXPR_CILK_SPAWN (*expr_p))
+        gimplify_cilk_detach (pre_p);
       gimplify_seq_add_stmt (pre_p, call);
       gsi = gsi_last (*pre_p);
       maybe_fold_stmt (&gsi);
@@ -5620,6 +5638,9 @@  gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	   SSA name w/o a definition.  We may have uses in the GIMPLE IL.
 	   ???  This doesn't make it a default-def.  */
 	SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
+
+      if (EXPR_CILK_SPAWN (*from_p))
+        gimplify_cilk_detach (pre_p);
       assign = call_stmt;
     }
   else
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index ca8945e..52ab2a8 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1201,6 +1201,9 @@  lto_init (void)
 {
   int i;
 
+  /* Initialize LTO-specific data structures.  */
+  in_lto_p = true;
+
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = (flag_wpa != NULL);
 
@@ -1283,9 +1286,6 @@  lto_init (void)
       }
 #undef NAME_TYPE
 
-  /* Initialize LTO-specific data structures.  */
-  in_lto_p = true;
-
   return true;
 }
 
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc
new file mode 100644
index 0000000..85990e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc
@@ -0,0 +1,47 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run } */
+/* { dg-require-effective-target cilkplus_runtime } */
+
+#include <unistd.h>
+extern "C" {
+  extern int __cilkrts_set_param (const char *, const char *);
+}
+
+int objcnt = 0;
+
+struct foo
+{
+  int live;
+  foo ()
+    { objcnt++; }
+  foo (const foo &)
+    { objcnt++; }
+  ~foo ()
+    { objcnt--; }
+};
+
+void
+spawnee (foo f)
+{
+  usleep(2000);
+  /* Now both my_test::f and spawnee::f should be alive.  */
+  if (objcnt != 2)
+    __builtin_abort ();
+}
+
+void
+my_test ()
+{
+  foo f;
+  _Cilk_spawn spawnee (f);
+  _Cilk_sync ;
+}
+
+int
+main ()
+{
+  if (__cilkrts_set_param ("nworkers", "2") != 0)
+    __builtin_abort ();
+
+  my_test ();
+}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index a646ecb..c76fc7b 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1194,6 +1194,10 @@  struct GTY(()) tree_base {
        SSA_NAME_OCCURS_IN_ABNORMAL_PHI in
            SSA_NAME
 
+       EXPR_CILK_SPAWN in
+           CALL_EXPR
+           AGGR_INIT_EXPR
+
    used_flag:
 
        TREE_USED in
diff --git a/gcc/tree.h b/gcc/tree.h
index 6851cd7..3bca90a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -894,6 +894,12 @@  extern void omp_clause_range_check_failed (const_tree, const char *, int,
 /* Cilk keywords accessors.  */
 #define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0)
 
+/* If this is true, we should insert a __cilk_detach call just before
+   this function call.  */
+#define EXPR_CILK_SPAWN(NODE) \
+  (tree_check2 (NODE, __FILE__, __LINE__, __FUNCTION__, \
+                CALL_EXPR, AGGR_INIT_EXPR)->base.u.bits.unsigned_flag)
+
 /* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is
    passed by invisible reference (and the TREE_TYPE is a pointer to the true
    type).  */
-- 
2.7.1