This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] implement sections directive
- From: Richard Henderson <rth at twiddle dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 25 Sep 2005 14:12:54 -0700
- Subject: [gomp] implement sections directive
Implemented to the same level as the for directive. That is, the
lastprivate, reduction clauses are unhandled.
r~
* builtin-types.def (BT_FN_UINT_UINT): New.
(BT_FN_VOID_UINT_UINT): Remove.
* omp-builtins.def (BUILT_IN_GOMP_SECTIONS_START): Use BT_FN_UINT_UINT.
* c-parser.c (c_parser_pragma_omp_section): Remove.
(c_parse_init): Use c_parser_pragma_omp_no_args instead.
(c_parser_section_scope): Remove.
(c_parser_omp_sections_body): New.
(c_parser_omp_directive): Use it.
(c_parser_pragma_omp_parallel_for): Remove inline marker.
(c_parser_pragma_omp_parallel_sections): Likewise.
* gimplify.c (gimplify_omp_sections, gimplify_omp_section): New.
(gimplify_expr): Use them.
fortran/
* types.def (BT_FN_UINT_UINT): New.
(BT_FN_VOID_UINT_UINT): Remove.
testsuite/
* gcc.dg/gomp/sections-1.c, gcc.dg/gomp/sections-2.c: New.
Index: builtin-types.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtin-types.def,v
retrieving revision 1.31.4.3
diff -u -p -r1.31.4.3 builtin-types.def
--- builtin-types.def 23 Sep 2005 23:02:04 -0000 1.31.4.3
+++ builtin-types.def 25 Sep 2005 21:05:28 -0000
@@ -181,6 +181,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_
DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT_WINT, BT_WINT)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@@ -269,7 +270,6 @@ DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_I1, B
DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_I2, BT_I2, BT_VOLATILE_PTR, BT_I2)
DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, BT_I4, BT_VOLATILE_PTR, BT_I4)
DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
-DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_LONGPTR,
BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
Index: c-parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parser.c,v
retrieving revision 2.17.4.19
diff -u -p -r2.17.4.19 c-parser.c
--- c-parser.c 25 Sep 2005 07:27:32 -0000 2.17.4.19
+++ c-parser.c 25 Sep 2005 21:05:29 -0000
@@ -199,7 +199,6 @@ static void c_parser_pragma_omp_critical
static void c_parser_pragma_omp_flush (cpp_reader *);
static void c_parser_pragma_omp_for (cpp_reader *);
static void c_parser_pragma_omp_parallel (cpp_reader *);
-static void c_parser_pragma_omp_section (cpp_reader *);
static void c_parser_pragma_omp_sections (cpp_reader *);
static void c_parser_pragma_omp_single (cpp_reader *);
static void c_parser_pragma_omp_threadprivate (cpp_reader *);
@@ -290,7 +289,7 @@ c_parse_init (void)
{ "master", c_parser_pragma_omp_no_args },
{ "ordered", c_parser_pragma_omp_no_args },
{ "parallel", c_parser_pragma_omp_parallel },
- { "section", c_parser_pragma_omp_section },
+ { "section", c_parser_pragma_omp_no_args },
{ "sections", c_parser_pragma_omp_sections },
{ "single", c_parser_pragma_omp_single },
{ "threadprivate", c_parser_pragma_omp_threadprivate }
@@ -6623,34 +6622,65 @@ c_parser_objc_keywordexpr (c_parser *par
section-directive[opt] structured-block
section-sequence section-directive structured-block */
-static tree
-c_parser_section_scope (c_parser *parser)
+static void
+c_parser_omp_sections_body (c_parser *parser, tree clauses)
{
- /* Taken from c_parser_compound_statement () */
- tree stmt;
+ tree stmt, substmt;
+ bool error_suppress = false;
+
if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- return error_mark_node;
+ return;
- stmt = c_begin_compound_stmt (true);
+ stmt = push_stmt_list ();
if (c_parser_peek_token (parser)->omp_kind != PRAGMA_OMP_SECTION)
- c_parser_statement (parser);
+ {
+ substmt = push_stmt_list ();
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
- if (c_parser_peek_token (parser)->omp_kind == PRAGMA_OMP_SECTION)
- {
- c_parser_pragma (parser);
- c_parser_statement (parser);
- }
- else
- {
- c_parser_error (parser, "%<#pragma omp section%> expected");
+ while (1)
+ {
+ c_parser_statement (parser);
+
+ if (c_parser_peek_token (parser)->omp_kind == PRAGMA_OMP_SECTION)
+ break;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ break;
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ break;
+ }
+
+ substmt = pop_stmt_list (substmt);
+ add_stmt (build1 (OMP_SECTION, void_type_node, substmt));
+ }
+
+ while (1)
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ break;
+ if (c_parser_next_token_is (parser, CPP_EOF))
break;
- }
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, 0);
+ if (c_parser_peek_token (parser)->omp_kind == PRAGMA_OMP_SECTION)
+ {
+ c_parser_pragma (parser);
+ error_suppress = false;
+ }
+ else if (!error_suppress)
+ {
+ error ("expected %<#pragma omp section%> or %<}%>");
+ error_suppress = true;
+ }
- return c_end_compound_stmt (stmt, true);
+ substmt = push_stmt_list ();
+ c_parser_statement (parser);
+ substmt = pop_stmt_list (substmt);
+ add_stmt (build1 (OMP_SECTION, void_type_node, substmt));
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+ "expected %<#pragma omp section%> or %<}%>");
+
+ stmt = pop_stmt_list (stmt);
+ add_stmt (build2 (OMP_SECTIONS, void_type_node, clauses, stmt));
}
/* Parse the expression for #pragma omp atomic. */
@@ -6755,7 +6785,7 @@ c_parser_omp_directive (c_parser *parser
case PRAGMA_OMP_PARALLEL_SECTIONS:
case PRAGMA_OMP_SECTIONS:
- add_stmt (c_parser_section_scope (parser));
+ c_parser_omp_sections_body (parser, clause);
break;
case PRAGMA_OMP_SINGLE:
@@ -7388,7 +7418,7 @@ c_parser_pragma_omp_for (cpp_reader *pfi
# pragma omp parallel for parallel-for-clause[optseq] new-line */
-static inline void
+static void
c_parser_pragma_omp_parallel_for (c_parser *parser)
{
while (c_parser_next_token_is_not (parser, CPP_EOF))
@@ -7442,7 +7472,7 @@ c_parser_pragma_omp_parallel_for (c_pars
#pragma omp parallel sections parallel-sections-clause[optseq] new-line */
-static inline void
+static void
c_parser_pragma_omp_parallel_sections (c_parser *parser)
{
while (c_parser_next_token_is_not (parser, CPP_EOF))
@@ -7552,20 +7582,6 @@ c_parser_pragma_omp_parallel (cpp_reader
}
/* OpenMP 2.5:
- # pragma omp section new-line */
-
-static void
-c_parser_pragma_omp_section (cpp_reader *pfile ATTRIBUTE_UNUSED)
-{
- printf ("#pragma omp section\n");
-
- if (c_parser_next_token_is_not (the_parser, CPP_EOF))
- {
- c_parser_error (the_parser, "expected new-line");
- }
-}
-
-/* OpenMP 2.5:
# pragma omp sections sections-clause[optseq] */
static void
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.135.4.16
diff -u -p -r2.135.4.16 gimplify.c
--- gimplify.c 25 Sep 2005 07:27:32 -0000 2.135.4.16
+++ gimplify.c 25 Sep 2005 21:05:29 -0000
@@ -55,7 +55,7 @@ static struct gimplify_ctx
tree exit_label;
tree return_temp;
- /* Two stack variables used for emit_omp_for_generic. These can be
+ /* Two stack variables used for gimplify_omp_for. These can be
reused throughout the function to preserve stack space. */
tree omp_for_istart, omp_for_iend;
@@ -4159,6 +4159,154 @@ gimplify_omp_for (tree *expr_p, tree *pr
}
+/* Gimplify an OMP_SECTIONS statement. In pseudo code, we generate
+
+ v = GOMP_sections_start (n);
+ L0:
+ switch (v)
+ {
+ case 0:
+ goto L2;
+ case 1:
+ section 1;
+ goto L1;
+ case 2:
+ ...
+ default:
+ abort ();
+ }
+ L1:
+ v = GOMP_sections_next ();
+ goto L0;
+ L2:
+*/
+
+static enum gimplify_status
+gimplify_omp_sections (tree *expr_p, tree *pre_p)
+{
+ VEC(tree,heap) *labels, *saved_labels;
+ tree saved_exit, label_vec;
+ tree l0, l1, l2, default_label;
+ tree t, u, v;
+ size_t i, len;
+
+ l0 = create_artificial_label ();
+ l1 = create_artificial_label ();
+ l2 = create_artificial_label ();
+ default_label = create_artificial_label ();
+ v = create_tmp_var (unsigned_type_node, ".section");
+
+ /* Process the body and create the switch statement simultaneously. */
+
+ saved_labels = gimplify_ctxp->case_labels;
+ saved_exit = gimplify_ctxp->exit_label;
+ gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
+ gimplify_ctxp->exit_label = l1;
+
+ gimplify_to_stmt_list (&OMP_SECTIONS_BODY (*expr_p));
+
+ labels = gimplify_ctxp->case_labels;
+ gimplify_ctxp->case_labels = saved_labels;
+ gimplify_ctxp->exit_label = saved_exit;
+
+ /* Convert the labels vector into a TREE_VEC that we can place in the
+ SWITCH_LABELS slot of the SWITCH_EXPR. Add case 0 for the "all done"
+ return value, and a default abort case for good measure. */
+
+ len = VEC_length (tree, labels);
+ label_vec = make_tree_vec (len + 2);
+ for (i = 0; i < len; ++i)
+ TREE_VEC_ELT (label_vec, i + 1) = VEC_index (tree, labels, i);
+
+ t = build3 (CASE_LABEL_EXPR, void_type_node,
+ build_int_cst (unsigned_type_node, 0), NULL, l2);
+ TREE_VEC_ELT (label_vec, 0) = t;
+
+ t = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, default_label);
+ TREE_VEC_ELT (label_vec, len + 1) = t;
+
+ VEC_free (tree, heap, labels);
+
+ /* Begin putting the statements together. */
+
+ t = build_int_cst (unsigned_type_node, len);
+ t = tree_cons (NULL, t, NULL);
+ u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
+ t = build_function_call_expr (u, t);
+ t = build2 (MODIFY_EXPR, void_type_node, v, t);
+ gimplify_and_add (t, pre_p);
+
+ t = build1 (LABEL_EXPR, void_type_node, l0);
+ gimplify_and_add (t, pre_p);
+
+ t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
+ gimplify_and_add (t, pre_p);
+
+ append_to_statement_list (OMP_SECTIONS_BODY (*expr_p), pre_p);
+
+ t = build1 (LABEL_EXPR, void_type_node, default_label);
+ gimplify_and_add (t, pre_p);
+
+ t = built_in_decls[BUILT_IN_TRAP];
+ t = build_function_call_expr (t, NULL);
+ gimplify_and_add (t, pre_p);
+
+ t = build1 (LABEL_EXPR, void_type_node, l1);
+ gimplify_and_add (t, pre_p);
+
+ t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
+ t = build_function_call_expr (t, NULL);
+ t = build2 (MODIFY_EXPR, void_type_node, v, t);
+ gimplify_and_add (t, pre_p);
+
+ t = build1 (GOTO_EXPR, void_type_node, l0);
+ gimplify_and_add (t, pre_p);
+
+ t = build1 (LABEL_EXPR, void_type_node, l2);
+ gimplify_and_add (t, pre_p);
+
+ /* Unless there's a nowait clause, add a barrier afterward. */
+
+ for (t = OMP_SECTIONS_CLAUSES (*expr_p); t ; t = TREE_CHAIN (t))
+ if (TREE_CODE (TREE_VALUE (t)) == OMP_CLAUSE_NOWAIT)
+ {
+ *expr_p = NULL;
+ return GS_ALL_DONE;
+ }
+
+ t = built_in_decls[BUILT_IN_GOMP_BARRIER];
+ *expr_p = build_function_call_expr (t, NULL);
+ return GS_OK;
+}
+
+
+/* Gimplify an OMP_SECTION. We treat this more or less like a case label.
+ Indeed, we create exactly that. */
+
+static enum gimplify_status
+gimplify_omp_section (tree *expr_p, tree *pre_p)
+{
+ tree lab, case_lab, t;
+ size_t n;
+
+ lab = create_artificial_label ();
+ t = build1 (LABEL_EXPR, void_type_node, lab);
+ gimplify_and_add (t, pre_p);
+
+ n = VEC_length (tree, gimplify_ctxp->case_labels) + 1;
+ t = build_int_cst (unsigned_type_node, n);
+ case_lab = build3 (CASE_LABEL_EXPR, void_type_node, t, NULL, lab);
+ VEC_safe_push (tree, heap, gimplify_ctxp->case_labels, case_lab);
+
+ gimplify_and_add (TREE_OPERAND (*expr_p, 0), pre_p);
+
+ t = build1 (GOTO_EXPR, void_type_node, gimplify_ctxp->exit_label);
+ *expr_p = t;
+
+ return GS_OK;
+}
+
+
/* Gimplify an OMP_CRITICAL statement. This is a relatively simple
substitution of a couple of function calls. But in the NAMED case,
requires that languages coordinate a symbol name. It is therefore
@@ -4935,6 +5083,14 @@ gimplify_expr (tree *expr_p, tree *pre_p
ret = gimplify_omp_for (expr_p, pre_p);
break;
+ case OMP_SECTIONS:
+ ret = gimplify_omp_sections (expr_p, pre_p);
+ break;
+
+ case OMP_SECTION:
+ ret = gimplify_omp_section (expr_p, pre_p);
+ break;
+
case OMP_CRITICAL:
ret = gimplify_omp_critical (expr_p, pre_p, post_p);
break;
Index: omp-builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/omp-builtins.def,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 omp-builtins.def
--- omp-builtins.def 25 Sep 2005 05:14:38 -0000 1.1.2.2
+++ omp-builtins.def 25 Sep 2005 21:05:29 -0000
@@ -123,7 +123,7 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_END, "GOMP_parallel_end",
BT_FN_VOID, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_START, "GOMP_sections_start",
- BT_FN_VOID_UINT_UINT, ATTR_NOTHROW_LIST)
+ BT_FN_UINT_UINT, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_NEXT, "GOMP_sections_next",
BT_FN_UINT, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_SECTIONS_START,
Index: fortran/types.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/Attic/types.def,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 types.def
--- fortran/types.def 23 Sep 2005 23:02:10 -0000 1.1.2.1
+++ fortran/types.def 25 Sep 2005 21:05:29 -0000
@@ -78,6 +78,7 @@ DEF_FUNCTION_TYPE_0 (BT_FN_VOID, BT_VOID
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTR, BT_VOID, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@@ -87,7 +88,6 @@ DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_I1, B
DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_I2, BT_I2, BT_VOLATILE_PTR, BT_I2)
DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, BT_I4, BT_VOLATILE_PTR, BT_I4)
DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
-DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I1_I1, BT_BOOL, BT_VOLATILE_PTR,
BT_I1, BT_I1)
Index: testsuite/gcc.dg/gomp/sections-1.c
===================================================================
RCS file: testsuite/gcc.dg/gomp/sections-1.c
diff -N testsuite/gcc.dg/gomp/sections-1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/gomp/sections-1.c 25 Sep 2005 21:05:29 -0000
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+
+extern void bar(int);
+
+void f1(void)
+{
+ #pragma omp sections nowait
+ {
+ bar (1);
+ #pragma omp section
+ bar (2);
+ #pragma omp section
+ bar (3);
+ #pragma omp section
+ bar (4);
+ #pragma omp section
+ bar (5);
+ }
+}
+
+void f2(void)
+{
+ #pragma omp sections
+ {
+ #pragma omp section
+ {
+ bar (1);
+ bar (1);
+ }
+ #pragma omp section
+ bar (2);
+ #pragma omp section
+ bar (3);
+ #pragma omp section
+ bar (4);
+ #pragma omp section
+ bar (5);
+ }
+}
Index: testsuite/gcc.dg/gomp/sections-2.c
===================================================================
RCS file: testsuite/gcc.dg/gomp/sections-2.c
diff -N testsuite/gcc.dg/gomp/sections-2.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/gomp/sections-2.c 25 Sep 2005 21:05:29 -0000
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+extern void bar(int);
+void foo(void)
+{
+ #pragma omp sections
+ bar (0); // { dg-error "expected" }
+
+ #pragma omp sections
+ {
+ } // { dg-error "expected" }
+
+ #pragma omp sections
+ {
+ bar (1);
+ }
+
+ #pragma omp sections
+ {
+ #pragma omp section
+ bar(2);
+ bar(3); // { dg-error "expected" }
+ bar(4);
+ #pragma omp section
+ bar(5);
+ bar(6); // { dg-error "expected" }
+ bar(7);
+ }
+}