[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