This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
+    }
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]