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]

[gomp4.5] Allow non-static data members in shared clause


Hi!

This patch adds support for non-static data members in shared clause.
The clause is after checking the constraints removed during the
gimplification, this in GCC can be firstprivate even with default(none)
and that is the best implementation for shared on the members.
We won't diagnose non-static data members not referenced in data sharing
clauses with default(none) though.

2015-10-29  Jakub Jelinek  <jakub@redhat.com>

gcc/cp/
	* cp-tree.h (omp_privatize_field): Add SHARED argument.
	* parser.c (cp_parser_omp_for_loop_init): Adjust omp_privatize_field
	caller.
	* pt.c (tsubst_omp_clauses): Handle non-static data members in
	shared clauses.
	(tsubst_omp_for_iterator): Adjust omp_privatize_field caller.
	* semantics.c (omp_privatize_field): Add SHARED argument, if true,
	always create artificial var and never put it into the hash table
	or vector.
	(handle_omp_array_sections_1): Adjust omp_privatize_field caller.
	(finish_omp_clauses): Likewise.  Allow non-static data members on
	shared clauses.
gcc/testsuite/
	* c-c++-common/gomp/element-1.c: New test.
	* g++.dg/gomp/clause-1.C (T::test): Don't expect error on
	non-static data member in shared clause.  Add single construct.
	* g++.dg/gomp/member-2.C (B::m2, B::m4): Don't expect error on
	non-static data member in shared clause.
	* g++.dg/gomp/member-3.C: New test.
	* g++.dg/gomp/member-4.C: New test.
libgomp/
	* testsuite/libgomp.c++/member-7.C: New test.
	* testsuite/libgomp.c++/member-6.C: New test.

--- gcc/cp/cp-tree.h.jj	2015-10-19 14:43:41.000000000 +0200
+++ gcc/cp/cp-tree.h	2015-10-29 14:18:11.005515191 +0100
@@ -6336,7 +6336,7 @@ extern void finish_omp_taskwait			(void)
 extern void finish_omp_taskyield		(void);
 extern void finish_omp_cancel			(tree);
 extern void finish_omp_cancellation_point	(tree);
-extern tree omp_privatize_field			(tree);
+extern tree omp_privatize_field			(tree, bool);
 extern tree begin_transaction_stmt		(location_t, tree *, int);
 extern void finish_transaction_stmt		(tree, tree, int, tree);
 extern tree build_transaction_expr		(location_t, tree, int, tree);
--- gcc/cp/parser.c.jj	2015-10-27 16:31:04.000000000 +0100
+++ gcc/cp/parser.c	2015-10-29 14:18:42.769059063 +0100
@@ -32634,7 +32634,7 @@ cp_parser_omp_for_loop_init (cp_parser *
 	      decl = cp_parser_lookup_name_simple (parser, name,
 						   token->location);
 	      if (TREE_CODE (decl) == FIELD_DECL)
-		add_private_clause = omp_privatize_field (decl);
+		add_private_clause = omp_privatize_field (decl, false);
 	    }
 	  cp_parser_abort_tentative_parse (parser);
 	  cp_parser_parse_tentatively (parser);
--- gcc/cp/pt.c.jj	2015-10-27 17:04:36.000000000 +0100
+++ gcc/cp/pt.c	2015-10-29 16:45:12.054177696 +0100
@@ -14465,6 +14465,7 @@ tsubst_omp_clauses (tree clauses, bool d
       if (allow_fields)
 	switch (OMP_CLAUSE_CODE (nc))
 	  {
+	  case OMP_CLAUSE_SHARED:
 	  case OMP_CLAUSE_PRIVATE:
 	  case OMP_CLAUSE_FIRSTPRIVATE:
 	  case OMP_CLAUSE_LASTPRIVATE:
@@ -14644,7 +14645,7 @@ tsubst_omp_for_iterator (tree t, int i,
 			&& DECL_NAME (v) == this_identifier)
 		      {
 			decl = TREE_OPERAND (decl, 1);
-			decl = omp_privatize_field (decl);
+			decl = omp_privatize_field (decl, false);
 		      }
 		    /* FALLTHRU */
 		  default:
--- gcc/cp/semantics.c.jj	2015-10-29 16:38:27.891964601 +0100
+++ gcc/cp/semantics.c	2015-10-29 18:28:36.740254434 +0100
@@ -4326,19 +4326,20 @@ omp_note_field_privatization (tree f, tr
    dummy VAR_DECL.  */
 
 tree
-omp_privatize_field (tree t)
+omp_privatize_field (tree t, bool shared)
 {
   tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
   if (m == error_mark_node)
     return error_mark_node;
-  if (!omp_private_member_map)
+  if (!omp_private_member_map && !shared)
     omp_private_member_map = new hash_map<tree, tree>;
   if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
     {
       gcc_assert (TREE_CODE (m) == INDIRECT_REF);
       m = TREE_OPERAND (m, 0);
     }
-  tree &v = omp_private_member_map->get_or_insert (t);
+  tree vb = NULL_TREE;
+  tree &v = shared ? vb : omp_private_member_map->get_or_insert (t);
   if (v == NULL_TREE)
     {
       v = create_temporary_var (TREE_TYPE (m));
@@ -4347,7 +4348,8 @@ omp_privatize_field (tree t)
       DECL_OMP_PRIVATIZED_MEMBER (v) = 1;
       SET_DECL_VALUE_EXPR (v, m);
       DECL_HAS_VALUE_EXPR_P (v) = 1;
-      omp_private_member_vec.safe_push (t);
+      if (!shared)
+	omp_private_member_vec.safe_push (t);
     }
   return v;
 }
@@ -4450,7 +4452,7 @@ handle_omp_array_sections_1 (tree c, tre
 
   if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
       && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
-    TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t));
+    TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
   ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
 				     maybe_zero_len, first_non_one, is_omp);
   if (ret == error_mark_node || ret == NULL_TREE)
@@ -5681,6 +5683,7 @@ finish_omp_clauses (tree clauses, bool a
       switch (OMP_CLAUSE_CODE (c))
 	{
 	case OMP_CLAUSE_SHARED:
+	  field_ok = allow_fields;
 	  goto check_dup_generic;
 	case OMP_CLAUSE_PRIVATE:
 	  field_ok = allow_fields;
@@ -5851,7 +5854,7 @@ finish_omp_clauses (tree clauses, bool a
 	  t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
 	  if (t)
 	    {
-	      if (!remove)
+	      if (!remove && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED)
 		omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
 	    }
 	  else
@@ -5896,7 +5899,9 @@ finish_omp_clauses (tree clauses, bool a
 	      && TREE_CODE (t) == FIELD_DECL
 	      && t == OMP_CLAUSE_DECL (c))
 	    {
-	      OMP_CLAUSE_DECL (c) = omp_privatize_field (t);
+	      OMP_CLAUSE_DECL (c)
+		= omp_privatize_field (t, (OMP_CLAUSE_CODE (c)
+					   == OMP_CLAUSE_SHARED));
 	      if (OMP_CLAUSE_DECL (c) == error_mark_node)
 		remove = true;
 	    }
@@ -7002,6 +7007,15 @@ finish_omp_clauses (tree clauses, bool a
 					 need_dtor))
 	remove = true;
 
+      if (!remove
+	  && c_kind == OMP_CLAUSE_SHARED
+	  && processing_template_decl)
+	{
+	  t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+	  if (t)
+	    OMP_CLAUSE_DECL (c) = t;
+	}
+
       if (remove)
 	*pc = OMP_CLAUSE_CHAIN (c);
       else
--- gcc/testsuite/c-c++-common/gomp/element-1.c.jj	2015-10-29 14:46:09.361381806 +0100
+++ gcc/testsuite/c-c++-common/gomp/element-1.c	2015-10-29 14:45:35.793864712 +0100
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+struct S { int a; };
+
+void
+foo (struct S *x)
+{
+  struct S b;
+  #pragma omp parallel private (b.a)	/* { dg-error "expected .\\). before .\\.. token" } */
+  ;
+  #pragma omp parallel private (x->a)	/* { dg-error "expected .\\). before .->. token" } */
+  ;
+}
--- gcc/testsuite/g++.dg/gomp/clause-1.C.jj	2015-10-14 10:25:28.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/clause-1.C	2015-10-29 14:47:47.233974078 +0100
@@ -12,7 +12,8 @@ void T::test()
   #pragma omp parallel private(n)
     n = 1;
 
-  #pragma omp parallel shared(n)	// { dg-error "T::n" }
+  #pragma omp parallel shared(n)
+  #pragma omp single
     n = 1;
 
   #pragma omp parallel firstprivate(n)
--- gcc/testsuite/g++.dg/gomp/member-2.C.jj	2015-10-14 10:25:28.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/member-2.C	2015-10-29 14:57:43.572415693 +0100
@@ -76,19 +76,19 @@ B::m2 ()
   #pragma omp parallel for reduction (+:g)	// { dg-error "has const type for .reduction." }
     for (int i = 0; i < 10; i++)
       ;
-  #pragma omp parallel shared (a)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (a)
     ;
-  #pragma omp parallel shared (b)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (b)
     ;
-  #pragma omp parallel shared (c)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (c)
     ;
-  #pragma omp parallel shared (e)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (e)
     ;
-  #pragma omp parallel shared (f)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (f)
     ;
-  #pragma omp parallel shared (g)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (g)
     ;
-  #pragma omp parallel shared (h)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (h)	// { dg-error "is predetermined .shared. for .shared." }
     ;
   return 0;
 }
@@ -150,19 +150,19 @@ B::m4 () const
   #pragma omp parallel for reduction (+:g)	// { dg-error "has const type for .reduction." }
     for (int i = 0; i < 10; i++)
       ;
-  #pragma omp parallel shared (a)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (a)	// { dg-error "is predetermined .shared. for .shared." }
     ;
-  #pragma omp parallel shared (b)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (b)
     ;
-  #pragma omp parallel shared (c)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (c)
     ;
-  #pragma omp parallel shared (e)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (e)
     ;
-  #pragma omp parallel shared (f)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (f)
     ;
-  #pragma omp parallel shared (g)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (g)
     ;
-  #pragma omp parallel shared (h)	// { dg-error "is not a variable in clause" }
+  #pragma omp parallel shared (h)	// { dg-error "is predetermined .shared. for .shared." }
     ;
   return 0;
 }
--- gcc/testsuite/g++.dg/gomp/member-3.C.jj	2015-10-29 14:27:12.404740649 +0100
+++ gcc/testsuite/g++.dg/gomp/member-3.C	2015-10-29 14:28:58.113218943 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S { int a; void foo (S *); static S &bar (); };
+
+void
+S::foo (S *x)
+{
+  S &b = bar ();
+  S c;
+  #pragma omp parallel private (b.a)	// { dg-error "expected .\\). before .\\.. token" }
+  ;
+  #pragma omp parallel private (c.a)	// { dg-error "expected .\\). before .\\.. token" }
+  ;
+  #pragma omp parallel private (x->a)	// { dg-error "expected .\\). before .->. token" }
+  ;
+}
--- gcc/testsuite/g++.dg/gomp/member-4.C.jj	2015-10-29 18:19:23.169188174 +0100
+++ gcc/testsuite/g++.dg/gomp/member-4.C	2015-10-29 18:20:28.353253961 +0100
@@ -0,0 +1,22 @@
+// { dg-do compile }
+
+class C { int a; char b; void foo (); };
+
+void
+C::foo ()
+{
+  #pragma omp parallel shared (a, a)	// { dg-error "appears more than once in data clauses" }
+  ;
+  #pragma omp parallel shared (a) private (b) shared(C::a)	// { dg-error "appears more than once in data clauses" }
+  ;
+  #pragma omp task private (a) private (b)
+  ;
+  #pragma omp task firstprivate (a) shared (C::a)	// { dg-error "appears more than once in data clauses" }
+  ;
+  #pragma omp parallel for lastprivate (b) firstprivate (a) lastprivate (b)	// { dg-error "appears more than once in data clauses" }
+  for (int i = 0; i < 64; i++)
+    ;
+  #pragma omp parallel for lastprivate (b) firstprivate (b)
+  for (int i = 0; i < 64; i++)
+    ;
+}
--- libgomp/testsuite/libgomp.c++/member-7.C.jj	2015-10-29 15:30:37.790224373 +0100
+++ libgomp/testsuite/libgomp.c++/member-7.C	2015-10-29 15:36:46.849921498 +0100
@@ -0,0 +1,119 @@
+// { dg-do run }
+
+#include <omp.h>
+
+int c, d, e;
+struct R { R () {}; ~R () {}; int r; };
+template <typename Q>
+struct T { T () : t(d) {}; virtual ~T () {}; Q t; };
+template <typename Q>
+struct A : public R, virtual public T<Q> { A () : b(c), a(e) {} Q a; int &b; void m1 (); };
+
+void
+take (int &a, int &b, int &c, int &d)
+{
+  asm volatile ("" : : "g" (&a), "g" (&b), "g" (&c), "g" (&d) : "memory");
+}
+
+template <typename Q>
+void
+A<Q>::m1 ()
+{
+  #pragma omp parallel private (a, T<Q>::t) shared (r, A::b) default(none)
+  {
+    int q = omp_get_thread_num (), q2;
+    a = q;
+    T<Q>::t = 3 * q;
+    #pragma omp single copyprivate (q2)
+    {
+      r = 2 * q;
+      b = 4 * q;
+      q2 = q;
+    }
+    take (a, r, T<Q>::t, b);
+    #pragma omp barrier
+    if (A::a != q || R::r != 2 * q2 || T<Q>::t != 3 * q || A::b != 4 * q2)
+      __builtin_abort ();
+  }
+  a = 7;
+  r = 8;
+  T<Q>::t = 9;
+  b = 10;
+  #pragma omp parallel shared (A::a) default (none) firstprivate (R::r, b) shared (T<Q>::t)
+  {
+    int q = omp_get_thread_num (), q2;
+    take (A::a, R::r, T<Q>::t, A::b);
+    if (a != 7 || r != 8 || T<Q>::t != 9 || b != 10)
+      __builtin_abort ();
+    R::r = 6 * q;
+    #pragma omp barrier
+    #pragma omp single copyprivate (q2)
+    {
+      A::a = 5 * q;
+      T<Q>::t = 7 * q;
+      q2 = q;
+    }
+    A::b = 8 * q;
+    take (a, r, T<Q>::t, b);
+    #pragma omp barrier
+    if (a != 5 * q2 || r != 6 * q || T<Q>::t != 7 * q2 || b != 8 * q)
+      __builtin_abort ();
+  }
+  a = 1;
+  b = 2;
+  R::r = 3;
+  T<Q>::t = 4;
+  bool f = false;
+  #pragma omp parallel private (f)
+    {
+      f = false;
+    #pragma omp single
+    #pragma omp taskloop default(none) firstprivate (r, A::a, f) shared (T<Q>::t, b)
+      for (int i = 0; i < 30; i++)
+	{
+	  int q = omp_get_thread_num ();
+	  int tv, bv;
+	  #pragma omp atomic read
+	  tv = T<Q>::t;
+	  #pragma omp atomic read
+	  bv = A::b;
+	  if (i == 16)
+	    {
+	      if (bv != 2 || tv != 4)
+		__builtin_abort ();
+	    }
+	  else
+	    {
+	      if ((bv != 2 && bv != 8) || (tv != 4 && tv != 9))
+		__builtin_abort ();
+	    }
+	  if (!f)
+	    {
+	      if (A::a != 1 || R::r != 3)
+		__builtin_abort ();
+	    }
+	  else if (a != 7 * q || r != 9 * q)
+	    __builtin_abort ();
+	  take (a, r, T<Q>::t, b);
+	  A::a = 7 * q;
+	  R::r = 9 * q;
+	  if (i == 16)
+	    {
+	      #pragma omp atomic write
+	      A::b = 8;
+	      #pragma omp atomic write
+	      T<Q>::t = 9;
+	    }
+	  f = true;
+	}
+    }
+}
+
+int
+main ()
+{
+  A<int> a;
+  a.m1 ();
+  A<int &> b;
+  b.m1 ();
+}
--- libgomp/testsuite/libgomp.c++/member-6.C.jj	2015-10-29 15:05:27.652746394 +0100
+++ libgomp/testsuite/libgomp.c++/member-6.C	2015-10-29 15:28:17.494210779 +0100
@@ -0,0 +1,114 @@
+// { dg-do run }
+
+#include <omp.h>
+
+struct R { R () {}; ~R () {}; int r; };
+struct T { T () {}; virtual ~T () {}; int t; };
+int c;
+struct A : public R, virtual public T { A () : b(c) {} int a; int &b; void m1 (); };
+
+void
+take (int &a, int &b, int &c, int &d)
+{
+  asm volatile ("" : : "g" (&a), "g" (&b), "g" (&c), "g" (&d) : "memory");
+}
+
+void
+A::m1 ()
+{
+  #pragma omp parallel private (a, T::t) shared (r, A::b) default(none)
+  {
+    int q = omp_get_thread_num (), q2;
+    a = q;
+    t = 3 * q;
+    #pragma omp single copyprivate (q2)
+    {
+      r = 2 * q;
+      b = 4 * q;
+      q2 = q;
+    }
+    take (a, r, t, b);
+    #pragma omp barrier
+    if (A::a != q || R::r != 2 * q2 || T::t != 3 * q || A::b != 4 * q2)
+      __builtin_abort ();
+  }
+  a = 7;
+  r = 8;
+  t = 9;
+  b = 10;
+  #pragma omp parallel shared (A::a) default (none) firstprivate (R::r, b) shared (t)
+  {
+    int q = omp_get_thread_num (), q2;
+    take (A::a, R::r, T::t, A::b);
+    if (a != 7 || r != 8 || t != 9 || b != 10)
+      __builtin_abort ();
+    R::r = 6 * q;
+    #pragma omp barrier
+    #pragma omp single copyprivate (q2)
+    {
+      A::a = 5 * q;
+      T::t = 7 * q;
+      q2 = q;
+    }
+    A::b = 8 * q;
+    take (a, r, t, b);
+    #pragma omp barrier
+    if (a != 5 * q2 || r != 6 * q || t != 7 * q2 || b != 8 * q)
+      __builtin_abort ();
+  }
+  a = 1;
+  b = 2;
+  R::r = 3;
+  t = 4;
+  bool f = false;
+  #pragma omp parallel private (f)
+    {
+      f = false;
+    #pragma omp single
+    #pragma omp taskloop default(none) firstprivate (r, A::a, f) shared (T::t, b)
+      for (int i = 0; i < 30; i++)
+	{
+	  int q = omp_get_thread_num ();
+	  int tv, bv;
+	  #pragma omp atomic read
+	  tv = t;
+	  #pragma omp atomic read
+	  bv = A::b;
+	  if (i == 16)
+	    {
+	      if (bv != 2 || tv != 4)
+		__builtin_abort ();
+	    }
+	  else
+	    {
+	      if ((bv != 2 && bv != 8) || (tv != 4 && tv != 9))
+		__builtin_abort ();
+	    }
+	  if (!f)
+	    {
+	      if (A::a != 1 || R::r != 3)
+		__builtin_abort ();
+	    }
+	  else if (a != 7 * q || r != 9 * q)
+	    __builtin_abort ();
+	  take (a, r, t, b);
+	  A::a = 7 * q;
+	  R::r = 9 * q;
+	  if (i == 16)
+	    {
+	      #pragma omp atomic write
+	      A::b = 8;
+	      #pragma omp atomic write
+	      T::t = 9;
+	    }
+	  f = true;
+	}
+    }
+}
+
+int
+main ()
+{
+  A a;
+  a.m1 ();
+}

	Jakub


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