Re: [Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE [PR86470]

2021-05-24 Thread Jakub Jelinek via Gcc-patches
On Wed, Mar 10, 2021 at 11:55:43AM +0100, Tobias Burnus wrote:
> --- a/gcc/fortran/trans-openmp.c
> +++ b/gcc/fortran/trans-openmp.c
> @@ -360,6 +360,39 @@ gfc_has_alloc_comps (tree type, tree decl)
>return false;
>  }
>  
> +/* Return true if TYPE is polymorphic but not with pointer attribute.  */
> +
> +static bool
> +gfc_is_polymorphic_nonptr (tree type)
> +{
> +  if (POINTER_TYPE_P (type))
> +type = TREE_TYPE (type);
> +  return GFC_CLASS_TYPE_P (type);
> +}
> +
> +/* Return true if TYPE is unlimited polymorphic but not with pointer 
> attribute;
> +   unlimited means also intrinsic types are handled and _len is used.  */
> +
> +static bool
> +gfc_is_unlimited_polymorphic_nonptr (tree type)
> +{
> +  if (POINTER_TYPE_P (type))
> +type = TREE_TYPE (type);
> +  if (!GFC_CLASS_TYPE_P (type))
> +return false;
> +
> +  tree field = TYPE_FIELDS (type); /* _data */
> +  gcc_assert (field);
> +  field = DECL_CHAIN (field); /* _vptr */
> +  gcc_assert (field);
> +  field = DECL_CHAIN (field);
> +  if (!field)
> +return false;
> +  gcc_assert (0 == strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field;

strcmp (...) == 0 instead please.

> +  return true;
> +}
> +
> +
>  /* Return true if DECL in private clause needs
> OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause.  */
>  bool
> @@ -743,12 +776,88 @@ tree
>  gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
>  {
>tree type = TREE_TYPE (dest), ptr, size, call;
> +  tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
>tree cond, then_b, else_b;
>stmtblock_t block, cond_block;
>  
>gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
> || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
>  
> +  if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
> +  && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
> +  && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
> +decl_type
> + = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));

Indentation, decl_type is indented by 4 spaces, but this line by tab (== 8 sp).

Otherwise LGTM, sorry for the delay.

Jakub



Re: [Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE [PR86470]

2021-05-23 Thread Tobias Burnus

*PING*

(OpenMP patches: I note that the reduction + firstprivate→tofrom patch
is still being reviewed and that there are bunch of recently posted
patches by ChungLin + Julian which are also pending review.)
(There is also one patch (affinity + iterator) I still have to repost –
and will happen soon.)

Tobias

On 10.03.21 11:55, Tobias Burnus wrote:

Belated follow-up to the patch from August ...
https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552588.html

This patch handles CLASS variables in the FIRSTPRIVATE data-sharing
clause, including freeing the memory at the end.

Technically this patch fixes a regression as the ICE is new –
before the code was just rejected. It is also rather contained.

OK for mainline?

Tobias

PS: The dtor can be extended rather simply to support arrays, for
the copy_ctor, some scalarization loop is needed.
Todo: 'private', which has to allocate the
dynamic type and copy the default initialization
for this the dynamic type.


-
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München 
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank 
Thürauf


[Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE [PR86470]

2021-03-10 Thread Tobias Burnus

Belated follow-up to the patch from August ...
https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552588.html

This patch handles CLASS variables in the FIRSTPRIVATE data-sharing
clause, including freeing the memory at the end.

Technically this patch fixes a regression as the ICE is new –
before the code was just rejected. It is also rather contained.

OK for mainline?

Tobias

PS: The dtor can be extended rather simply to support arrays, for
the copy_ctor, some scalarization loop is needed.
Todo: 'private', which has to allocate the
dynamic type and copy the default initialization
for this the dynamic type.

-
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München 
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank 
Thürauf
OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE [PR86470]

gcc/fortran/ChangeLog:

	PR fortran/86470
	* trans-expr.c (gfc_copy_class_to_class): Add unshare_expr.
	* trans-openmp.c (gfc_is_polymorphic_nonptr,
	gfc_is_unlimited_polymorphic_nonptr): New.
	(gfc_omp_clause_copy_ctor, gfc_omp_clause_dtor): Handle
	polymorphic scalars.

libgomp/ChangeLog:

	PR fortran/86470
	* testsuite/libgomp.fortran/class-firstprivate-1.f90: New test.
	* testsuite/libgomp.fortran/class-firstprivate-2.f90: New test.
	* testsuite/libgomp.fortran/class-firstprivate-3.f90: New test.

gcc/testsuite/ChangeLog:

	PR fortran/86470
	* gfortran.dg/gomp/class-firstprivate-1.f90: New test.
	* gfortran.dg/gomp/class-firstprivate-2.f90: New test.
	* gfortran.dg/gomp/class-firstprivate-3.f90: New test.
	* gfortran.dg/gomp/class-firstprivate-4.f90: New test.

 gcc/fortran/trans-expr.c   |   2 +-
 gcc/fortran/trans-openmp.c | 162 +-
 .../gfortran.dg/gomp/class-firstprivate-1.f90  |  62 
 .../gfortran.dg/gomp/class-firstprivate-2.f90  |  54 
 .../gfortran.dg/gomp/class-firstprivate-3.f90  |  61 
 .../gfortran.dg/gomp/class-firstprivate-4.f90  |  44 +++
 .../libgomp.fortran/class-firstprivate-1.f90   | 323 
 .../libgomp.fortran/class-firstprivate-2.f90   | 334 +
 .../libgomp.fortran/class-firstprivate-3.f90   | 334 +
 9 files changed, 1374 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 85c16d7f4c3..5389b9a4a37 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1524,7 +1524,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
 	{
 	  vec_safe_push (args, from_len);
 	  vec_safe_push (args, to_len);
-	  extcopy = build_call_vec (fcn_type, fcn, args);
+	  extcopy = build_call_vec (fcn_type, unshare_expr (fcn), args);
 	  tmp = fold_build2_loc (input_location, GT_EXPR,
  logical_type_node, from_len,
  build_zero_cst (TREE_TYPE (from_len)));
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 349df1cc346..7c25241a863 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -360,6 +360,39 @@ gfc_has_alloc_comps (tree type, tree decl)
   return false;
 }
 
+/* Return true if TYPE is polymorphic but not with pointer attribute.  */
+
+static bool
+gfc_is_polymorphic_nonptr (tree type)
+{
+  if (POINTER_TYPE_P (type))
+type = TREE_TYPE (type);
+  return GFC_CLASS_TYPE_P (type);
+}
+
+/* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
+   unlimited means also intrinsic types are handled and _len is used.  */
+
+static bool
+gfc_is_unlimited_polymorphic_nonptr (tree type)
+{
+  if (POINTER_TYPE_P (type))
+type = TREE_TYPE (type);
+  if (!GFC_CLASS_TYPE_P (type))
+return false;
+
+  tree field = TYPE_FIELDS (type); /* _data */
+  gcc_assert (field);
+  field = DECL_CHAIN (field); /* _vptr */
+  gcc_assert (field);
+  field = DECL_CHAIN (field);
+  if (!field)
+return false;
+  gcc_assert (0 == strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field;
+  return true;
+}
+
+
 /* Return true if DECL in private clause needs
OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause.  */
 bool
@@ -743,12 +776,88 @@ tree
 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
 {
   tree type = TREE_TYPE (dest), ptr, size, call;
+  tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
   tree cond, then_b, else_b;
   stmtblock_t block, cond_block;
 
   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
 	  || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
 
+  if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
+  && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
+  && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
+decl_type
+	= TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
+
+  if (gfc_is_polymorphic_nonptr (decl_type))
+{
+  if (POINTER_TYPE_P (decl_type))
+	decl_type = TREE_TYPE (decl_type);
+  decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
+

Re: [Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE (PR86470)

2020-08-31 Thread Jakub Jelinek via Gcc-patches
On Tue, Aug 25, 2020 at 12:50:46PM +0200, Tobias Burnus wrote:
> OK for mainline?

Generally, you know Fortran FE much more than I do, so just a few random
comments.

> --- a/gcc/fortran/trans-openmp.c
> +++ b/gcc/fortran/trans-openmp.c
> @@ -355,6 +355,51 @@ gfc_has_alloc_comps (tree type, tree decl)
>return false;
>  }
>  
> +/* Return true if TYPE is polymorphic but not with pointer attribute.  */
> +
> +static bool
> +gfc_is_polymorphic_nonptr (tree type)
> +{
> +  if (POINTER_TYPE_P (type))
> +type = TREE_TYPE (type);
> +  if (TREE_CODE (type) != RECORD_TYPE)
> +return false;
> +
> +  tree field = TYPE_FIELDS (type);
> +  if (!field || 0 != strcmp ("_data", IDENTIFIER_POINTER (DECL_NAME 
> (field
> +return false;
> +  field = DECL_CHAIN (field);
> +  if (!field || 0 != strcmp ("_vptr", IDENTIFIER_POINTER (DECL_NAME 
> (field

Is it safe to just look at the field names?  Shouldn't it at least also
test that the fields are DECL_ARTIFICIAL, or somehow else ensure that it
isn't a user derived type with _data and _vptr fields in it.

  type foo
integer :: _data
integer :: _vptr
integer :: _len
  end type
  type(foo) :: a
  a%_data = 1
  a%_vptr = 2
  a%_len = 3
end
compiles just fine with -fallow-leading-underscore ...

> @@ -740,6 +785,87 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree 
> src)
>gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
> || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
>  
> +  /* TODO: implement support for polymorphic arrays; reject for now.  */
> +  /* Void arrays appear as var.0 = var._data.data. A bit hackish to
> + distinguish from 'type(c_ptr) :: var(5)' by scanning for '.';
> + this assumes that ASM_FORMAT_PRIVATE_NAME uses a '.', which most
> + systems do. */
> +  if (TREE_CODE (type) == ARRAY_TYPE
> +  && TREE_TYPE (type) == pvoid_type_node
> +  && TREE_CODE (dest) == MEM_REF
> +  && strchr (IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (dest, 0))), 
> '.'))

This seems very fragile, there are targets that use $ instead, other targets
use only underscores.
$ grep NO_DOT_IN_LABEL config/* config/*/* 2>/dev/null
config/vx-common.h:# define NO_DOT_IN_LABEL
config/mmix/mmix.h:#define NO_DOT_IN_LABEL
config/nvptx/nvptx.h:#define NO_DOT_IN_LABEL
config/xtensa/elf.h:#define NO_DOT_IN_LABEL
$ grep -w NO_DOLLAR_IN_LABEL config/* config/*/* 2>/dev/null
config/dragonfly.h:#undef NO_DOLLAR_IN_LABEL
config/elfos.h:#define NO_DOLLAR_IN_LABEL
config/freebsd.h:#undef NO_DOLLAR_IN_LABEL
config/vx-common.h:# undef NO_DOLLAR_IN_LABEL
config/alpha/alpha.h:#undef NO_DOLLAR_IN_LABEL
config/arm/aout.h:#ifndef NO_DOLLAR_IN_LABEL
config/arm/aout.h:#define NO_DOLLAR_IN_LABEL 1
config/mips/n32-elf.h:#define NO_DOLLAR_IN_LABEL
config/mmix/mmix.h:#define NO_DOLLAR_IN_LABEL
config/rs6000/rs6000.c:#ifdef NO_DOLLAR_IN_LABEL
config/rs6000/rs6000-protos.h:#ifdef NO_DOLLAR_IN_LABEL
config/rs6000/xcoff.h:#define NO_DOLLAR_IN_LABEL
config/tilegx/tilegx.h:#undef NO_DOLLAR_IN_LABEL
config/tilepro/tilepro.h:#undef NO_DOLLAR_IN_LABEL
config/xtensa/elf.h:#undef NO_DOLLAR_IN_LABEL

Couldn't it be recorded somewhere in DECL_LANG_SPECIFIC of the decl?

> +fatal_error (input_location,
> +  "Sorry, polymorphic arrays not yet supported for "
> +  "firstprivate");

Shouldn't this be sorry ("...") instead?

> +  /* var._data - _data is void* for scalars and descriptor for arrays.  
> */
> +  if (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == RECORD_TYPE)
> + fatal_error (input_location,
> +  "Sorry, polymorphic arrays not yet supported for "
> +  "firstprivate");

Likewise.

> +  /* Malloc memory + call class->_vpt->_copy.  */
> +  call = builtin_decl_explicit (BUILT_IN_MALLOC);

Is malloc what the FE uses elsewhere for it?  Will something free it
afterwards?

> +  if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1)))
> + {
> +   gfc_add_block_to_block (, _block);
> + }

Formatting, one stmt shouldn't be wrapped into {}s.

Jakub



Re: [Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE (PR86470)

2020-08-31 Thread Tobias Burnus

Hi Andre,

On 8/31/20 12:55 PM, Andre Vehreschild wrote:

+gfc_is_unlimited_polymorphic_nonptr (tree type)
+  tree field = TYPE_FIELDS (type); /* _data */
+  if (!field)

^^^ here you don't . So theoretically this routine could match a type which
has a _len as its third field, but that is not a unlim-poly class. Maybe factor
out the test from the above routine and unify with this one to reuse the test
for a BT_CLASS?!


Granted. The reason was the code use:
if (polymophic)
  {
  ...
  if (unlimited_polymorphic)

Hence, I assumed that that check was already done, reducing
code size (but having less universality) and increasing
(cold-code) performance.

My new idea is to unify the two functions and add an
"bool only_unlimited" flag.


Btw, I believe the first routine can be better replaced by:

static bool
gfc_is_polymorphic_nonptr (tree type)
{
   if (POINTER_TYPE_P (type))
 type = TREE_TYPE (type);
   return GFC_CLASS_TYPE_P (type);
}


Maybe. However, when looking into the check for polymorphic
arrays, the DECL_LANG_SPECIFIC (and I think TYPE_LANG_SPECIFIC)
were present but contained only garbage. Thus, it might not work.
(I have to check.) – If it works, I will use your nicer suggestion.
If it doesn't work, I would go for my proposal above.
(Eventually, in a follow-up patch for polymorphic arrays, it has
to be fixed properly to avoid the following hack.)


+  /* TODO: implement support for polymorphic arrays; reject for now.  */
+  /* Void arrays appear as var.0 = var._data.data. A bit hackish to
+ distinguish from 'type(c_ptr) :: var(5)' by scanning for '.';
+ this assumes that ASM_FORMAT_PRIVATE_NAME uses a '.', which most
+ systems do. */
...
I totally agree that this is hackish and I don't like for that. But I can't
come up with a better solution at the moment.


I think some changes at multiple places are needed to implement this
properly – but for the 'sorry' I did not want to do non-local changes;
for the real version, it should use some nicer code!

Thanks for the suggestions and review.

Tobias

PS: I want to first finish working on some other tasks before coming back
to this patch.



Re: [Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE (PR86470)

2020-08-31 Thread Andre Vehreschild
Hi Tobias,

in (look for ^^^):

diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 063d4c145e2..705cdc7749f 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -355,6 +355,51 @@ gfc_has_alloc_comps (tree type, tree decl)
   return false;
 }

+/* Return true if TYPE is polymorphic but not with pointer attribute.  */
+
+static bool
+gfc_is_polymorphic_nonptr (tree type)
+{
+  if (POINTER_TYPE_P (type))
+type = TREE_TYPE (type);
+  if (TREE_CODE (type) != RECORD_TYPE)
+return false;
+
+  tree field = TYPE_FIELDS (type);
+  if (!field || 0 != strcmp ("_data", IDENTIFIER_POINTER (DECL_NAME (field

^^^ here you are comparing the field - name

+return false;
+  field = DECL_CHAIN (field);
+  if (!field || 0 != strcmp ("_vptr", IDENTIFIER_POINTER (DECL_NAME (field
+return false;
+
+  return true;
+}
+
+/* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
+   unlimited means also intrinsic types are handled and _len is used.  */
+
+static bool
+gfc_is_unlimited_polymorphic_nonptr (tree type)
+{
+  if (POINTER_TYPE_P (type))
+type = TREE_TYPE (type);
+  if (TREE_CODE (type) != RECORD_TYPE)
+return false;
+
+  tree field = TYPE_FIELDS (type); /* _data */
+  if (!field)

^^^ here you don't . So theoretically this routine could match a type which
has a _len as its third field, but that is not a unlim-poly class. Maybe factor
out the test from the above routine and unify with this one to reuse the test
for a BT_CLASS?!

+return false;
+  field = DECL_CHAIN (field); /* _vptr */
+  if (!field)
+return false;
+  field = DECL_CHAIN (field);
+  if (!field || 0 != strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field
+return false;
+
+  return true;
+}
+
+

---

Btw, I believe the first routine can be better replaced by:

static bool
gfc_is_polymorphic_nonptr (tree type)
{
  if (POINTER_TYPE_P (type))
type = TREE_TYPE (type);
  return GFC_CLASS_TYPE_P (type);
}

I have no better solution for learning whether a tree's type is unlimited poly
yet.


@@ -740,6 +785,87 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
  || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);

+  /* TODO: implement support for polymorphic arrays; reject for now.  */
+  /* Void arrays appear as var.0 = var._data.data. A bit hackish to
+ distinguish from 'type(c_ptr) :: var(5)' by scanning for '.';
+ this assumes that ASM_FORMAT_PRIVATE_NAME uses a '.', which most
+ systems do. */
+  if (TREE_CODE (type) == ARRAY_TYPE
+  && TREE_TYPE (type) == pvoid_type_node
+  && TREE_CODE (dest) == MEM_REF
+  && strchr (IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (dest, 0))), '.'))
+fatal_error (input_location,
+"Sorry, polymorphic arrays not yet supported for "
+"firstprivate");

I totally agree that this is hackish and I don't like for that. But I can't
come up with a better solution at the moment.

The remainder looks ok to me.

Regards,
Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de


Re: [Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE (PR86470)

2020-08-31 Thread Tobias Burnus

*PING* — For this part 1/n patch series.

On 8/25/20 12:50 PM, Tobias Burnus wrote:

This patch adds support for polymorphic variables ("CLASS")
to OpenMP's data-sharing clause FIRSTPRIVATE.

While the patch should be okay, there is more follow-up
work required, but one has to make a start :-)

* PRIVATE – as used in the testcase of the PR is not yet supported,
  only FIRSTPRIVATE.
* polymorphic arrays are not supported (see 'sorry').
– For nonallocatable arrays, the decl passed to the function
  does contain much information; the LANG_SPECIFIC is non-NULL
  its the pointer components contain garbage :-(
– Handling noncharacter polymorphic arrays (hence: non-unlimited
  polymorphic) seems to be simpler; the current patch seems to
  work for some cases already, if the "sorry" is commented.
* ...

OK for mainline?

Tobias

PS: Supporting *map*ing of polymorphic variables is another matter,
which is unfortunately even harder.


-
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter


[Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE (PR86470)

2020-08-25 Thread Tobias Burnus

This patch adds support for polymorphic variables ("CLASS")
to OpenMP's data-sharing clause FIRSTPRIVATE.

While the patch should be okay, there is more follow-up
work required, but one has to make a start :-)

* PRIVATE – as used in the testcase of the PR is not yet supported,
  only FIRSTPRIVATE.
* polymorphic arrays are not supported (see 'sorry').
– For nonallocatable arrays, the decl passed to the function
  does contain much information; the LANG_SPECIFIC is non-NULL
  its the pointer components contain garbage :-(
– Handling noncharacter polymorphic arrays (hence: non-unlimited
  polymorphic) seems to be simpler; the current patch seems to
  work for some cases already, if the "sorry" is commented.
* ...

OK for mainline?

Tobias

PS: Supporting *map*ing of polymorphic variables is another matter,
which is unfortunately even harder.

-
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter
[Patch] OpenMP/Fortran: Handle polymorphic scalars in data-sharing FIRSTPRIVATE (PR86470)

gcc/fortran/ChangeLog:

	PR fortran/86470
	* trans-expr.c (gfc_copy_class_to_class): Add unshare_expr.
	* trans-openmp.c (gfc_is_polymorphic_nonptr,
	gfc_is_unlimited_polymorphic_nonptr): New.
	(gfc_omp_clause_copy_ctor): Handle polymorphic variables.

libgomp/ChangeLog:

	PR fortran/86470
	* testsuite/libgomp.fortran/class-firstprivate-1.f90: New test.
	* testsuite/libgomp.fortran/class-firstprivate-2.f90: New test.
	* testsuite/libgomp.fortran/class-firstprivate-3.f90: New test.

gcc/testsuite/ChangeLog:

	PR fortran/86470
	* gfortran.dg/gomp/class-firstprivate-1.f90: New test.
	* gfortran.dg/gomp/class-firstprivate-2.f90: New test.
	* gfortran.dg/gomp/class-firstprivate-3.f90: New test.

 gcc/fortran/trans-expr.c   |   2 +-
 gcc/fortran/trans-openmp.c | 126 +
 gcc/testsuite/gfortran.dg/gomp/class-firstprivate-1.f90|  62 ++
 gcc/testsuite/gfortran.dg/gomp/class-firstprivate-2.f90|  54 ++
 gcc/testsuite/gfortran.dg/gomp/class-firstprivate-3.f90|  61 ++
 libgomp/testsuite/libgomp.fortran/class-firstprivate-1.f90 | 323 +++
 libgomp/testsuite/libgomp.fortran/class-firstprivate-2.f90 | 334 +
 libgomp/testsuite/libgomp.fortran/class-firstprivate-3.f90 | 334 +
 8 files changed, 1295 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 36ff9b5cbc6..b0c38e9f444 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1451,7 +1451,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
 	{
 	  vec_safe_push (args, from_len);
 	  vec_safe_push (args, to_len);
-	  extcopy = build_call_vec (fcn_type, fcn, args);
+	  extcopy = build_call_vec (fcn_type, unshare_expr (fcn), args);
 	  tmp = fold_build2_loc (input_location, GT_EXPR,
  logical_type_node, from_len,
  build_zero_cst (TREE_TYPE (from_len)));
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 063d4c145e2..705cdc7749f 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -355,6 +355,51 @@ gfc_has_alloc_comps (tree type, tree decl)
   return false;
 }
 
+/* Return true if TYPE is polymorphic but not with pointer attribute.  */
+
+static bool
+gfc_is_polymorphic_nonptr (tree type)
+{
+  if (POINTER_TYPE_P (type))
+type = TREE_TYPE (type);
+  if (TREE_CODE (type) != RECORD_TYPE)
+return false;
+
+  tree field = TYPE_FIELDS (type);
+  if (!field || 0 != strcmp ("_data", IDENTIFIER_POINTER (DECL_NAME (field
+return false;
+  field = DECL_CHAIN (field);
+  if (!field || 0 != strcmp ("_vptr", IDENTIFIER_POINTER (DECL_NAME (field
+return false;
+
+  return true;
+}
+
+/* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
+   unlimited means also intrinsic types are handled and _len is used.  */
+
+static bool
+gfc_is_unlimited_polymorphic_nonptr (tree type)
+{
+  if (POINTER_TYPE_P (type))
+type = TREE_TYPE (type);
+  if (TREE_CODE (type) != RECORD_TYPE)
+return false;
+
+  tree field = TYPE_FIELDS (type); /* _data */
+  if (!field)
+return false;
+  field = DECL_CHAIN (field); /* _vptr */
+  if (!field)
+return false;
+  field = DECL_CHAIN (field);
+  if (!field || 0 != strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field
+return false;
+
+  return true;
+}
+
+
 /* Return true if DECL in private clause needs
OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause.  */
 bool
@@ -740,6 +785,87 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
 	  || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
 
+  /* TODO: implement support for