[committed] Fix OpenMP C/C++ default(none) handling (PR c/85696)

Message ID 20180511080520.GM8577@tucnak
State New
Headers show
Series
  • [committed] Fix OpenMP C/C++ default(none) handling (PR c/85696)
Related show

Commit Message

Jakub Jelinek May 11, 2018, 8:05 a.m.
Hi!

While we explicitly firstprivatize temporaries used in VLA size
computations, if the VLAs are indirect (pointer to VLA) or struct element
pointer to VLA etc., the temporaries are just handled using the default
sharing.  For C/C++ that works fine as long as default(none) isn't used, at
which point we get errors on those.  In Fortran we already "predetermine"
those shared, this patch does the same for C/C++.  For C++, we actually need
to treat it more like first rule of implicit determination, because we use
DECL_ARTIFICIAL integral vars for loop constructs with random access
iterators (except for pointers).

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk,
queued for release branch backporting.

2018-05-11  Jakub Jelinek  <jakub@redhat.com>

	PR c/85696
	* c-omp.c (c_omp_predetermined_sharing): Return
	OMP_CLAUSE_DEFAULT_SHARED for artificial vars with integral type.

	* cp-tree.h (cxx_omp_predetermined_sharing_1): New prototype.
	* cp-gimplify.c (cxx_omp_predetermined_sharing): New wrapper around
	cxx_omp_predetermined_sharing_1.  Rename old function to ...
	(cxx_omp_predetermined_sharing_1): ... this.
	* semantics.c (finish_omp_clauses): Use cxx_omp_predetermined_sharing_1
	instead of cxx_omp_predetermined_sharing.

	* c-c++-common/gomp/pr85696.c: New test.


	Jakub

Patch

--- gcc/c-family/c-omp.c.jj	2018-05-09 20:12:25.826258355 +0200
+++ gcc/c-family/c-omp.c	2018-05-10 16:32:10.483325735 +0200
@@ -1611,5 +1611,13 @@  c_omp_predetermined_sharing (tree decl)
   if (TREE_READONLY (decl))
     return OMP_CLAUSE_DEFAULT_SHARED;
 
+  /* Predetermine artificial variables holding integral values, those
+     are usually result of gimplify_one_sizepos or SAVE_EXPR
+     gimplification.  */
+  if (VAR_P (decl)
+      && DECL_ARTIFICIAL (decl)
+      && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+    return OMP_CLAUSE_DEFAULT_SHARED;
+
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
--- gcc/cp/cp-tree.h.jj	2018-05-08 13:56:41.180932180 +0200
+++ gcc/cp/cp-tree.h	2018-05-10 16:46:32.625146394 +0200
@@ -7383,6 +7383,7 @@  extern int cp_gimplify_expr			(tree *, g
 						 gimple_seq *);
 extern void cp_genericize			(tree);
 extern bool cxx_omp_const_qual_no_mutable	(tree);
+extern enum omp_clause_default_kind cxx_omp_predetermined_sharing_1 (tree);
 extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
 extern tree cxx_omp_clause_default_ctor		(tree, tree, tree);
 extern tree cxx_omp_clause_copy_ctor		(tree, tree, tree);
--- gcc/cp/cp-gimplify.c.jj	2018-05-10 09:37:30.951224415 +0200
+++ gcc/cp/cp-gimplify.c	2018-05-10 16:50:27.510369823 +0200
@@ -1957,7 +1957,7 @@  cxx_omp_const_qual_no_mutable (tree decl
 /* True if OpenMP sharing attribute of DECL is predetermined.  */
 
 enum omp_clause_default_kind
-cxx_omp_predetermined_sharing (tree decl)
+cxx_omp_predetermined_sharing_1 (tree decl)
 {
   /* Static data members are predetermined shared.  */
   if (TREE_STATIC (decl))
@@ -1973,6 +1973,32 @@  cxx_omp_predetermined_sharing (tree decl
     return OMP_CLAUSE_DEFAULT_SHARED;
 
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+}
+
+/* Likewise, but also include the artificial vars.  We don't want to
+   disallow the artificial vars being mentioned in explicit clauses,
+   as we use artificial vars e.g. for loop constructs with random
+   access iterators other than pointers, but during gimplification
+   we want to treat them as predetermined.  */
+
+enum omp_clause_default_kind
+cxx_omp_predetermined_sharing (tree decl)
+{
+  enum omp_clause_default_kind ret = cxx_omp_predetermined_sharing_1 (decl);
+  if (ret != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+    return ret;
+
+  /* Predetermine artificial variables holding integral values, those
+     are usually result of gimplify_one_sizepos or SAVE_EXPR
+     gimplification.  */
+  if (VAR_P (decl)
+      && DECL_ARTIFICIAL (decl)
+      && INTEGRAL_TYPE_P (TREE_TYPE (decl))
+      && !(DECL_LANG_SPECIFIC (decl)
+	   && DECL_OMP_PRIVATIZED_MEMBER (decl)))
+    return OMP_CLAUSE_DEFAULT_SHARED;
+
+  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
 
 /* Finalize an implicitly determined clause.  */
--- gcc/cp/semantics.c.jj	2018-05-09 20:12:27.578259853 +0200
+++ gcc/cp/semantics.c	2018-05-10 16:46:20.443134802 +0200
@@ -7297,7 +7297,7 @@  finish_omp_clauses (tree clauses, enum c
 
 	  if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
 	    share_name = "threadprivate";
-	  else switch (cxx_omp_predetermined_sharing (t))
+	  else switch (cxx_omp_predetermined_sharing_1 (t))
 	    {
 	    case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
 	      break;
--- gcc/testsuite/c-c++-common/gomp/pr85696.c.jj	2018-05-10 16:32:10.484325736 +0200
+++ gcc/testsuite/c-c++-common/gomp/pr85696.c	2018-05-10 16:32:10.484325736 +0200
@@ -0,0 +1,20 @@ 
+/* PR c/85696 */
+
+#ifndef __cplusplus
+void
+foo (int n, int a[][n])
+{
+  #pragma omp parallel shared(a) default(none)
+  #pragma omp master
+    a[23][0] = 42;
+}
+#endif
+
+void
+bar (int n, void *p)
+{
+  int (*a)[n] = (int (*)[n]) p;
+  #pragma omp parallel shared(a) default(none)
+  #pragma omp master
+    a[23][0] = 42;
+}