[PATCH] Fix #pragma omp task cgraph issues (PR c++/36523)

Jakub Jelinek jakub@redhat.com
Sun Jun 15 18:07:00 GMT 2008


Hi!

The attached testcase doesn't link, as the copy constructor which
is only ever called from the *.omp_cpyfn* generated routine isn't emitted.
The problem is that the function is lowered too late and at that point
the copy constructor has been already cgraph_release_function_body'ed
as unneeded.  While the *.omp_cpyfn* had the GENERIC body generated
already in the pass_lower_omp, it hasn't been registered with
cgraph and gimplified until pass_expand_omp.
The following patch (the omp-low.c hunks) move its gimplification
and registration with cgraph to pass_lower_omp (it has to be delayed
until all omp lowering finishes to avoid calling gimplify_body
when within another gimple context).  Unfortunately, this leads
to many regressions, the *.omp_cpyfn* function doesn't seem to be
emitted when -funit-at-a-time.

The cgraphbuild.c hunk just makes sure that build_cgraph_edges recognizes
them as needed.  The *.omp_cpyfn* is created and registered with
cgraph during pass_lower_omp of the related function, and during
build_cgraph_edges it is cgraph_mark_needed_node.  But then later
on cgraph_process_new_functions forcibly overwrites the needed flag
back to false, so nothing recognizes the function as needed.

Honza, what's the reason for node->needed = false in
cgraph_process_new_functions?  Isn't it by default false from
cgraph_create_node (and similarly node->reachable)?  So why it is cleared
again?  I admit I've tested this patch so far just with OpenMP make
checking, not full bootstrap, but if it is cleared, then I don't see
where it could be marked as needed again.  Can you please have a look?
Thanks.

2008-06-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/36523
	* cgraphunit.c (cgraph_process_new_functions): Don't clear
	node->needed.
	* cgraphbuild.c (record_reference): Handle OMP_PARALLEL and OMP_TASK.
	* omp-low.c (delete_omp_context): Call finalize_task_copyfn.
	(expand_task_call): Don't call expand_task_copyfn.
	(expand_task_copyfn): Renamed to...
	(finalize_task_copyfn): ... this.

	* testsuite/libgomp.c++/task-7.C: New function.

--- gcc/cgraphunit.c	(revision 136748)
+++ gcc/cgraphunit.c	(working copy)
@@ -443,7 +443,7 @@ cgraph_process_new_functions (void)
 	     it into reachable functions list.  */
 
 	  node->next_needed = NULL;
-	  node->needed = node->reachable = false;
+	  node->reachable = false;
 	  cgraph_finalize_function (fndecl, false);
 	  cgraph_mark_reachable_node (node);
 	  output = true;
--- gcc/cgraphbuild.c	(revision 136748)
+++ gcc/cgraphbuild.c	(working copy)
@@ -62,6 +62,24 @@ record_reference (tree *tp, int *walk_su
 	}
       break;
 
+    case OMP_PARALLEL:
+      if (flag_unit_at_a_time)
+	{
+	  if (OMP_PARALLEL_FN (*tp))
+	    cgraph_mark_needed_node (cgraph_node (OMP_PARALLEL_FN (*tp)));
+	}
+      break;
+
+    case OMP_TASK:
+      if (flag_unit_at_a_time)
+	{
+	  if (OMP_TASK_FN (*tp))
+	    cgraph_mark_needed_node (cgraph_node (OMP_TASK_FN (*tp)));
+	  if (OMP_TASK_COPYFN (*tp))
+	    cgraph_mark_needed_node (cgraph_node (OMP_TASK_COPYFN (*tp)));
+	}
+      break;
+
     default:
       /* Save some cycles by not walking types and declaration as we
 	 won't find anything useful there anyway.  */
--- gcc/omp-low.c	(revision 136748)
+++ gcc/omp-low.c	(working copy)
@@ -1188,6 +1188,37 @@ new_omp_context (tree stmt, omp_context 
   return ctx;
 }
 
+static void maybe_catch_exception (tree *stmt_p);
+
+/* Finalize task copyfn.  */
+
+static void
+finalize_task_copyfn (tree task_stmt)
+{
+  struct function *child_cfun;
+  tree child_fn, old_fn;
+
+  child_fn = OMP_TASK_COPYFN (task_stmt);
+  if (child_fn == NULL_TREE)
+    return;
+
+  child_cfun = DECL_STRUCT_FUNCTION (child_fn);
+
+  /* Inform the callgraph about the new function.  */
+  DECL_STRUCT_FUNCTION (child_fn)->curr_properties
+    = cfun->curr_properties;
+
+  old_fn = current_function_decl;
+  push_cfun (child_cfun);
+  current_function_decl = child_fn;
+  gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
+  maybe_catch_exception (&BIND_EXPR_BODY (DECL_SAVED_TREE (child_fn)));
+  pop_cfun ();
+  current_function_decl = old_fn;
+
+  cgraph_add_new_function (child_fn, false);
+}
+
 /* Destroy a omp_context data structures.  Called through the splay tree
    value delete callback.  */
 
@@ -1218,6 +1249,9 @@ delete_omp_context (splay_tree_value val
 	DECL_ABSTRACT_ORIGIN (t) = NULL;
     }
 
+  if (is_task_ctx (ctx))
+    finalize_task_copyfn (ctx->stmt);
+
   XDELETE (ctx);
 }
 
@@ -2882,35 +2916,6 @@ expand_parallel_call (struct omp_region 
 }
 
 
-static void maybe_catch_exception (tree *stmt_p);
-
-
-/* Finalize task copyfn.  */
-
-static void
-expand_task_copyfn (tree task_stmt)
-{
-  struct function *child_cfun;
-  tree child_fn, old_fn;
-
-  child_fn = OMP_TASK_COPYFN (task_stmt);
-  child_cfun = DECL_STRUCT_FUNCTION (child_fn);
-
-  /* Inform the callgraph about the new function.  */
-  DECL_STRUCT_FUNCTION (child_fn)->curr_properties
-    = cfun->curr_properties;
-
-  old_fn = current_function_decl;
-  push_cfun (child_cfun);
-  current_function_decl = child_fn;
-  gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
-  maybe_catch_exception (&BIND_EXPR_BODY (DECL_SAVED_TREE (child_fn)));
-  pop_cfun ();
-  current_function_decl = old_fn;
-
-  cgraph_add_new_function (child_fn, false);
-}
-
 /* Build the function call to GOMP_task to actually
    generate the task operation.  BB is the block where to insert the code.  */
 
@@ -2922,9 +2927,6 @@ expand_task_call (basic_block bb, tree e
 
   clauses = OMP_TASK_CLAUSES (entry_stmt);
 
-  if (OMP_TASK_COPYFN (entry_stmt))
-    expand_task_copyfn (entry_stmt);
-
   c = find_omp_clause (clauses, OMP_CLAUSE_IF);
   if (c)
     cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
--- libgomp/testsuite/libgomp.c++/task-7.C	(revision 0)
+++ libgomp/testsuite/libgomp.c++/task-7.C	(revision 0)
@@ -0,0 +1,18 @@
+// PR c++/36523
+// { dg-do run }
+
+template<typename T>
+struct A
+{
+  A() { }
+  A(const A&) { }
+  void foo() { }
+};
+
+int main()
+{
+  A<int> a;
+  #pragma omp task firstprivate (a)
+    a.foo();
+  return 0;
+}

	Jakub



More information about the Gcc-patches mailing list