[Patch] OpenMP/Fortran: Fix handling of 'declare target' with 'link' clause [PR11555]

2024-06-21 Thread Tobias Burnus

Hi all,

it turned out that 'declare target' with 'link' clause was broken in multiple 
ways.

The main fix is the attached patch, i.e. namely pushing the variables already to
the offload-vars list already in the FE.

When implementing it, I noticed:
* C has a similar issue when using nested functions, which is
  a GNU extension →https://gcc.gnu.org/115574

* When doing partial mapping of arrays (which is one of the reasons for 'link'),
  offsets are mishandled in Fortran (not tested in C), see FIXME in the patch)
  There: arr2(10) should print 10 but with map(arr2(10:)) it prints 19.
  (I will file a PR about this).

* It might happen that linked variables do not get linked. I have not 
investigated
  why, but 'arr2' gives link errors – while 'arr' works.
  See FIXME in the patch. (I will file a PR about this)

* For COMMON blocks, map(/common/) is rejected,https://gcc.gnu.org/PR115577

* When then mapping map(a,b,c) which is identical for 'common /mycom/ a,b,c',
  it fails to link the device side as the 'mycom_' symbol cannot be found on the
  device side.  (I will file a PR about this)

As COMMON as issues, an alternative would be to defer the trans-common.cc
changes to a later patch.

Comments, questions, concerns?

Tobias

PS: Tested with nvptx offloading with a page-migration supporting system with
nvptx and GCN offloading configured and no new fails observed.
OpenMP/Fortran: Fix handling of 'declare target' with 'link' clause [PR11555]

Contrary to a normal 'declare target', the 'declare target link' attribute
also needs to set node->offloadable and push the offload_vars in the front end.

Linked variables require that the data is mapped. For module variables, this
can happen anywhere. For variables in an external subprograms or the main
programm, this can only happen in the either that program itself or in an
internal subprogram. - Whether a variable is just normally mapped or linked then
becomes relevant if a device routine exists that can access that variable,
i.e. an internal procedure has then to be marked as declare target.

	PR fortran/115559

gcc/fortran/ChangeLog:

	* trans-common.cc (build_common_decl): Add 'omp declare target' and
	'omp declare target link' variables to offload_vars.
	* trans-decl.cc (add_attributes_to_decl): Likewise; update args and
	call decl_attributes.
	(get_proc_pointer_decl, gfc_get_extern_function_decl,
	build_function_decl): Update calls.
	(gfc_get_symbol_decl): Likewise; move after 'DECL_STATIC (t)=1'
	to avoid errors with symtab_node::get_create.

libgomp/ChangeLog:

	* testsuite/libgomp.fortran/declare-target-link.f90: New test.

 gcc/fortran/trans-common.cc|  21 
 gcc/fortran/trans-decl.cc  |  81 +-
 .../libgomp.fortran/declare-target-link.f90| 119 +
 3 files changed, 195 insertions(+), 26 deletions(-)

diff --git a/gcc/fortran/trans-common.cc b/gcc/fortran/trans-common.cc
index 5f44e7bd663..e714342c3c0 100644
--- a/gcc/fortran/trans-common.cc
+++ b/gcc/fortran/trans-common.cc
@@ -98,6 +98,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "cgraph.h"
+#include "context.h"
+#include "omp-offload.h"
 #include "gfortran.h"
 #include "trans.h"
 #include "stringpool.h"
@@ -497,6 +500,24 @@ build_common_decl (gfc_common_head *com, tree union_type, bool is_init)
 	  = tree_cons (get_identifier ("omp declare target"),
 		   omp_clauses, DECL_ATTRIBUTES (decl));
 
+  if (com->omp_declare_target_link || com->omp_declare_target)
+	{
+	  /* Add to offload_vars; get_create does so for omp_declare_target,
+	 omp_declare_target_link requires manual work.  */
+	  gcc_assert (symtab_node::get (decl) == 0);
+	  symtab_node *node = symtab_node::get_create (decl);
+	  if (node != NULL && com->omp_declare_target_link)
+	{
+	  node->offloadable = 1;
+	  if (ENABLE_OFFLOADING)
+		{
+		  g->have_offload = true;
+		  if (is_a  (node))
+		vec_safe_push (offload_vars, decl);
+		}
+	}
+	}
+
   /* Place the back end declaration for this common block in
  GLOBAL_BINDING_LEVEL.  */
   gfc_map_of_all_commons[identifier] = pushdecl_top_level (decl);
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 8d4f06a4e1d..4067dd6ed77 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -46,7 +46,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "trans-stmt.h"
 #include "gomp-constants.h"
 #include "gimplify.h"
+#include "context.h"
 #include "omp-general.h"
+#include "omp-offload.h"
 #include "attr-fnspec.h"
 #include "tree-iterator.h"
 #include "dependency.h"
@@ -1470,19 +1472,18 @@ gfc_add_assign_aux_vars (gfc_symbol * sym)
 }
 
 
-static tree
-add_attributes_to_decl (symbol_attribute sym_attr, tree list)
+static void
+add_attributes_to_decl (tree *decl_p, const gfc_symbol *sym)
 {
   unsigned id;
-  tree attr;
+  tree list = 

Re: [Patch, PR Fortran/90072] Polymorphic Dispatch to Polymophic Return Type Memory Leak

2024-06-08 Thread Tobias Burnus

Andre Vehreschild wrote:

PS That's good news about the funding. Maybe we will get to see "built in"
coarrays soon?

You hopefully will see Nikolas work on the shared memory coarray support, if
that is what you mean by "built in" coarrays. I will be working on the
distributed memory coarray support esp. fixing the module issues and some other
team related things.


Cool! (Both of it.)

I assume "distributed memory coarray support" is still based on Open
Coarrays?

* * *

I am asking because there is coarray API being defined: Parallel Runtime
Interface for Fortran (PRIF), https://go.lbl.gov/prif

with an implementation called Caffeine – CoArray Fortran Framework of
Efficient Interfaces to Network Environments,
https://crd.lbl.gov/caffeine which uses GASNet or POSIX processes.

Well, the among the implementers is (unsurprising?) Damian – and the
idea seems to be that LLVM's FLANG will use the API.

Tobias

PS: I think it might be useful in the long run to support both
PRIF/Caffeine and OpenCoarrays.

I have attached my hello-world patch for -fcoarray=prif that I wrote
after ISC-HPC; it only handles this_image() / num_images() + init/stop.
I got confirmation by the PRIF developers that the next revision will
permit calling __prif_MOD_prif_init multiple times such that one can use
it in the constructor for static coarrays, which won't work otherwise.
gcc/ChangeLog:

	* flag-types.h (enum gfc_fcoarray):

gcc/fortran/ChangeLog:

	* invoke.texi:
	* lang.opt:
	* trans-decl.cc (gfc_build_builtin_function_decls):
	(create_main_function):
	* trans-intrinsic.cc (trans_this_image):
	(trans_num_images):
	* trans.h (GTY):

 gcc/flag-types.h   |  3 ++-
 gcc/fortran/invoke.texi|  7 +-
 gcc/fortran/lang.opt   |  5 +++-
 gcc/fortran/trans-decl.cc  | 56 --
 gcc/fortran/trans-intrinsic.cc | 42 +++
 gcc/fortran/trans.h|  5 
 6 files changed, 108 insertions(+), 10 deletions(-)

diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 5a2b461fa75..babd747c01d 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -427,7 +427,8 @@ enum gfc_fcoarray
 {
   GFC_FCOARRAY_NONE = 0,
   GFC_FCOARRAY_SINGLE,
-  GFC_FCOARRAY_LIB
+  GFC_FCOARRAY_LIB,
+  GFC_FCOARRAY_PRIF
 };
 
 
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 40e8e4a7cdd..331a40d31db 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -1753,7 +1753,12 @@ Single-image mode, i.e. @code{num_images()} is always one.
 
 @item @samp{lib}
 Library-based coarray parallelization; a suitable GNU Fortran coarray
-library needs to be linked.
+library needs to be linked such as @url{http://opencoarrays.org}.
+
+@item @samp{prif}
+Using the Parallel Runtime Interface for Fortran (PRIF),
+@url{https://go.lbl.gov/@/prif}; for instance, via Caffeine,
+@url{https://go.lbl.gov/@/caffeine}.
 @end table
 
 
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 5efd4a0129a..9ba957d5571 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -786,7 +786,7 @@ Copy array sections into a contiguous block on procedure entry.
 
 fcoarray=
 Fortran RejectNegative Joined Enum(gfc_fcoarray) Var(flag_coarray) Init(GFC_FCOARRAY_NONE)
--fcoarray=	Specify which coarray parallelization should be used.
+-fcoarray=	Specify which coarray parallelization should be used.
 
 Enum
 Name(gfc_fcoarray) Type(enum gfc_fcoarray) UnknownError(Unrecognized option: %qs)
@@ -800,6 +800,9 @@ Enum(gfc_fcoarray) String(single) Value(GFC_FCOARRAY_SINGLE)
 EnumValue
 Enum(gfc_fcoarray) String(lib) Value(GFC_FCOARRAY_LIB)
 
+EnumValue
+Enum(gfc_fcoarray) String(prif) Value(GFC_FCOARRAY_PRIF)
+
 fcheck=
 Fortran RejectNegative JoinedOrMissing
 -fcheck=[...]	Specify which runtime checks are to be performed.
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index dca7779528b..d1c0e2ee997 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -170,6 +170,10 @@ tree gfor_fndecl_co_sum;
 tree gfor_fndecl_caf_is_present;
 tree gfor_fndecl_caf_random_init;
 
+tree gfor_fndecl_prif_init;
+tree gfor_fndecl_prif_stop;
+tree gfor_fndecl_prif_this_image_no_coarray;
+tree gfor_fndecl_prif_num_images;
 
 /* Math functions.  Many other math functions are handled in
trans-intrinsic.cc.  */
@@ -4147,6 +4151,31 @@ gfc_build_builtin_function_decls (void)
 	get_identifier (PREFIX("caf_random_init")),
 	void_type_node, 2, logical_type_node, logical_type_node);
 }
+  else if (flag_coarray == GFC_FCOARRAY_PRIF)
+{
+  tree pint_type = build_pointer_type (integer_type_node);
+  tree pbool_type = build_pointer_type (boolean_type_node);
+  tree pintmax_type_node = get_typenode_from_name (INTMAX_TYPE);
+  pintmax_type_node = build_pointer_type (pintmax_type_node);
+
+  gfor_fndecl_prif_init = gfc_build_library_function_decl_with_spec (
+	get_identifier ("__prif_MOD_prif_init"), ". W ",
+	void_type_node, 1, 

Re: [committed] nvptx, libgfortran: Switch out of "minimal" mode

2024-06-06 Thread Tobias Burnus

Sandra Loosemore wrote:

On 6/6/24 06:06, Tobias Burnus wrote:
+@item I/O within OpenMP target regions and OpenACC compute regions 
is supported

+  using the C library @code{printf} functions.
+  Additionally, the Fortran @code{print}/@code{write} 
statements are
+  supported within OpenMP target regions, but not yet OpenACC 
compute
+  regions.  @c The latter needs 
'GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE'.




I think an "in" (or 'within') is missing before OpenACC.


Yes, "...not yet within OpenACC compute regions", please.


Thanks! Committed as https://gcc.gnu.org/r15-1072-g423522aacd9f30

Tobias



Re: [committed] nvptx, libgfortran: Switch out of "minimal" mode

2024-06-06 Thread Tobias Burnus

Hi Thomas,

regarding the commit r15-1070-g3a4775d4403f2e / https://gcc.gnu.org/r15-1070

First, thanks for adding I/O support to nvptx offloading.

I have a wording nit, to be confirmed by a native speaker:


--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi

...

+@item I/O within OpenMP target regions and OpenACC compute regions is 
supported

+  using the C library @code{printf} functions.
+  Additionally, the Fortran @code{print}/@code{write} statements are
+  supported within OpenMP target regions, but not yet OpenACC compute
+  regions.  @c The latter needs 
'GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE'.




I think an "in" (or 'within') is missing before OpenACC.

Otherwise, it seemed to fine at a glance – and I am happy that that 
feature now finally works :-)


Hooray, no longer using reverse offload ("!$omp target 
device(ancestor:1)") for Fortran I/O when debugging.


Thanks,

Tobias


[wwwdocs][patch] gcc-15/changes.html: Fortran - mention F2023 logical-kind additions

2024-05-28 Thread Tobias Burnus
Let's make https://gcc.gnu.org/gcc-15/changes.html a bit more useful … 
While there were several useful Fortran commits already, only one seems 
to be about a new feature.


Thus, document selected_logical_kind and the ISO_FORTRAN_ENV additions.

Comments or suggestions before I commit it?

Tobias
Title: GCC 15 Release Series — Changes, New Features, and Fixes








GCC 15 Release SeriesChanges, New Features, and Fixes


This page is a "brief" summary of some of the huge number of improvements
in GCC 15.



Note: GCC 15 has not been released yet, so this document is
a work-in-progress.


Caveats

  ...




General Improvements


New Languages and Language specific improvements










Fortran


  Fortran 2023: The selected_logical_kind intrinsic function
  and, in the ISO_FORTRAN_ENV module, the named constants
  logical{8,16,32,64} and real16 were added.








New Targets and Target Specific Improvements








































Operating Systems



























Other significant improvements










Re: [Patch] Fortran: invoke.texi - link to OpenCoarrays.org + mention libcaf_single

2024-05-21 Thread Tobias Burnus

Hi Bernhard,

rep.dot@gmail.com wrote:

library such as @url{http://opencoarrays.org} needs to be linked.

Maybe use https?


Works, but as the certificate is not valid, it requires to ignore the 
errors in a browser, which is a worse user experience.


The error is, e.g.,

"curl: (60) SSL certificate problem: self-signed certificate"

Or at 
https://www.ssllabs.com/ssltest/analyze.html?d=www.opencoarrays.org=on


"Common names: invalid-sni.invalid / Issuer: invalid-sni.invalid  
(Self-signed)"


@Damian: Can you fix the server to actually have a valid certificate?

Tobias


[Patch] Fortran: Fix SHAPE for zero-size arrays

2024-05-19 Thread Tobias Burnus
That is for https://gcc.gnu.org/PR115150 – a GCC 12/13/14/15 regression, 
caused when switching from a libgomp call to inline code and missing the 
corner case of zero-size arrays ...


OK for mainline + all affected branches?

Tobias
Fortran: Fix SHAPE for zero-size arrays

	PR fortran/115150

gcc/fortran/ChangeLog:

	* trans-intrinsic.cc (gfc_conv_intrinsic_bound): Fix SHAPE
	for zero-size arrays

gcc/testsuite/ChangeLog:

	* gfortran.dg/shape_12.f90: New test.

 gcc/fortran/trans-intrinsic.cc |  4 ++-
 gcc/testsuite/gfortran.dg/shape_12.f90 | 51 ++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 80dc3426ab0..912c1000e18 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -3090,7 +3090,9 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
   lbound, gfc_index_one_node);
 	}
   else if (op == GFC_ISYM_SHAPE)
-	se->expr = size;
+	se->expr = fold_build2_loc (input_location, MAX_EXPR,
+gfc_array_index_type, size,
+gfc_index_zero_node);
   else
 	gcc_unreachable ();
 
diff --git a/gcc/testsuite/gfortran.dg/shape_12.f90 b/gcc/testsuite/gfortran.dg/shape_12.f90
new file mode 100644
index 000..e672e1ff9f9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/shape_12.f90
@@ -0,0 +1,51 @@
+! { dg-do run }
+!
+! PR fortran/115150
+!
+! Check that SHAPE handles zero-sized arrays correctly
+!
+implicit none
+call one
+call two
+
+contains
+
+subroutine one
+  real,allocatable :: A(:),B(:,:)
+  allocate(a(3:0), b(5:1, 2:5))
+
+  if (any (shape(a) /= [0])) stop 1
+  if (any (shape(b) /= [0, 4])) stop 2
+  if (size(a) /= 0) stop 3
+  if (size(b) /= 0) stop 4
+  if (any (lbound(a) /= [1])) stop 5
+  if (any (lbound(b) /= [1, 2])) stop 6
+  if (any (ubound(a) /= [0])) stop 5
+  if (any (ubound(b) /= [0,5])) stop 6
+end
+
+subroutine two
+integer :: x1(10), x2(10,10)
+call f(x1, x2, -3)
+end
+
+subroutine f(y1, y2, n)
+  integer, value :: n
+  integer :: y1(1:n)
+  integer :: y2(1:n,4,2:*)
+  call g(y1, y2)
+end
+
+subroutine g(z1, z2)
+  integer :: z1(..), z2(..)
+
+  if (any (shape(z1) /= [0])) stop 1
+  if (any (shape(z2) /= [0, 4, -1])) stop 2
+  if (size(z1) /= 0) stop 3
+  if (size(z2) /= 0) stop 4
+  if (any (lbound(z1) /= [1])) stop 5
+  if (any (lbound(z2) /= [1, 1, 1])) stop 6
+  if (any (ubound(z1) /= [0])) stop 5
+  if (any (ubound(z2) /= [0, 4, -1])) stop 6
+end
+end


[Patch] Fortran: invoke.texi - link to OpenCoarrays.org + mention libcaf_single

2024-05-19 Thread Tobias Burnus
I noticed that gfortran's coarray support did not link to the 
http://www.opencoarrays.org/


As that library is needed to support parallelization, it makes sense to 
have the link.


Motivated by someone claiming at ISC-HPC that GCC only supports a single 
image.


And also motivated by Damian's presentation, which showed that 
gfortran's coarrays could successfully run the ICAR atmospheric model 
with 25,600 processes (OpenCoarrays with OpenSHMEM backend), which 
definitely is more than one image :-)


I think mentioning the existing libcaf_single is still useful, even 
though it is only of limited use (except that it does ship with GCC and 
permits to do some testings. Especially, it is used by GCC's testsuite).


OK for mainline?

Tobias
Fortran: invoke.texi - link to OpenCoarrays.org + mention libcaf_single

gcc/fortran/ChangeLog:

	* invoke.texi (fcoarray): Link to OpenCoarrays.org;
	mention libcaf_single.

 gcc/fortran/invoke.texi | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 40e8e4a7cdd..78a2910b8d8 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -1753,7 +1753,10 @@ Single-image mode, i.e. @code{num_images()} is always one.
 
 @item @samp{lib}
 Library-based coarray parallelization; a suitable GNU Fortran coarray
-library needs to be linked.
+library needs to be linked such as @url{http://opencoarrays.org}.
+Alternatively, GCC's @code{libcaf_single} library can be linked,
+albeit it only supports a single image.
+
 @end table
 
 


Re: Mattermost discussion on PR98426

2024-04-26 Thread Tobias Burnus

Hi Bernhard, hello all,

Bernhard Reutner-Fischer wrote:

PS: unfortunately the git branch (
https://gcc.gnu.org/git/?p=gcc.git;a=log;h=refs/heads/aldot/fortran-fe-stringpool
  ) mentioned in mail (I) lived in the old git, before we switched to
git, and i fear that branch maybe got lost.


Try gcc-old.git instead:

https://gcc.gnu.org/git/?p=gcc-old.git;a=log;h=refs/heads/aldot/fortran-fe-stringpool

Tobias

Generated files in libgfortran for Fortran intrinsic procedures (was: Updated Sourceware infrastructure plans)

2024-04-18 Thread Tobias Burnus

Hi Janne,

Janne Blomqvist wrote:

back when I was active I did think about this
issue. IMHO the best of my ideas was to convert these into C++
templates.


I think this will work – but we have to be super careful:

With C++, there is the problem that we definitely do not want to add 
dependency on libstdc++ nor to use some features which require special 
hardware support (like exceptions [always bad], symbol aliases, ...). — 
On some systems, a full C++ support might be not available, like 
embedded systems (including some odd embedded OS) or offloading devices.


The libstdc++ dependency would be detected by linking as we currently 
do. For in-language features, we have to ensure the appropriate flags 
-fno-exceptions (and probably a few more). And it should be clear what 
language features to use.


If we do, I think that would surely be an option.


What we're essentially doing with the M4 stuff and the
proposed in-house Python reimplementation is to make up for lack of
monomorphization in plain old C. Rather than doing some DIY templates,
switch the implementation language to something which has that feature
built-in, in this case C++.  No need to convert the entire libgfortran
to C++ if you don't want to, just those objects that are generated
from the M4 templates. Something like

template
void matmul(T* a, T* b, T* c, ...)
{
// actual matmul code here
}

extern "C" {
   // Instantiate template for every type and export the symbol
   void matmul_r4(gfc_array_r4* a, gfc_array_r4* b, gfc_array_r4* c, ...)
   {
 matmul(a, b, c, ...);
   }
   // And so on for other types
}


Cheers,

Tobias


[Patch] Fortran: List-directed read - accept again tab as alternative to space as separator [PR114304] (was: [patch, libgfortran] PR114304 - [13/14 Regression] libgfortran I/O – bogus "Semicolon not a

2024-04-08 Thread Tobias Burnus

Jerry D wrote:

See attached updated patch.


It turned rather quickly out that this patch – committed as 
r14-9822-g93adf88cc6744a – caused regressions.


Namely, real-world code use tab(s) as separator instead of spaces.

[For instance, PR114304 which contains a named-list input file from SPEC 
CPU 2017; that example uses tabs before the '=' sign, but the issue is 
more generic.]


I think the ISO Fortran standard only permits spaces, but as it feels 
natural and is widely supported, tabs are used and should remain supported.


It is not quite clear how '\r' are or should be handled, but as 
eat_spaces did use it, I thought I would add one testcase using them as 
well.


That test is not affected by my change; it did work before with GCC and 
still does – but it does fail with ifort/ifx/flang. I have not thought 
deeply whether it should be supported or not – and looking at the 
libgfortran source file, it often but (→ testcase) not consistently 
requires that an \n follows the \r.


OK for mainline? [And: When the previous patch gets backported, this 
surely needs to be included as well.]


Tobias
Fortran: Accept again tab as alternative to space as separator [PR114304]

This fixes a side-effect of/regression caused by r14-9822-g93adf88cc6744a,
which was for the same PR.

	PR libfortran/114304

libgfortran/ChangeLog:

	* io/list_read.c (eat_separator): Accept tab as alternative to space.

gcc/testsuite/ChangeLog:

	* gfortran.dg/pr114304-2.f90: New test.

 gcc/testsuite/gfortran.dg/pr114304-2.f90 | 82 
 libgfortran/io/list_read.c   |  2 +-
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gfortran.dg/pr114304-2.f90 b/gcc/testsuite/gfortran.dg/pr114304-2.f90
new file mode 100644
index 000..5ef5874f528
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr114304-2.f90
@@ -0,0 +1,82 @@
+! { dg-do run }
+!
+! PR fortran/114304
+!
+! Ensure that '\t' (tab) is supported as separator in list-directed input
+! While not really standard conform, this is widely used in user input and
+! widely supported.
+!
+
+use iso_c_binding
+implicit none
+character(len=*,kind=c_char), parameter :: tab = C_HORIZONTAL_TAB
+
+! Accept '' as variant to ' ' as separator
+! Check that  and  are handled
+
+character(len=*,kind=c_char), parameter :: nml_str &
+   = ''//C_CARRIAGE_RETURN // C_NEW_LINE // &
+ 'first'//tab//'='//tab//' .true.'// C_NEW_LINE // &
+ ' , other'//tab//' ='//tab//'3'//tab//', 2'//tab//'/'
+
+! Check that  is handled,
+
+! Note: For new line, Unix uses \n, Windows \r\n but old Apple systems used '\r'
+!
+! Gfortran does not seem to support all \r, but the following is supported
+! since ages, ! which seems to be a gfortran extension as ifort and flang don't like it.
+
+character(len=*,kind=c_char), parameter :: nml_str2 &
+   = ''//C_CARRIAGE_RETURN // C_NEW_LINE // &
+ 'first'//C_NEW_LINE//'='//tab//' .true.'// C_CARRIAGE_RETURN // &
+ ' , other'//tab//' ='//tab//'3'//tab//', 2'//tab//'/'
+
+character(len=*,kind=c_char), parameter :: str &
+   = tab//'1'//tab//'2,'//tab//'3'//tab//',4'//tab//','//tab//'5'//tab//'/'
+character(len=*,kind=c_char), parameter :: str2 &
+   = tab//'1'//tab//'2;'//tab//'3'//tab//';4'//tab//';'//tab//'5'//tab//'/'
+logical :: first
+integer :: other(4)
+integer :: ints(6)
+namelist /inparm/ first , other
+
+other = 1
+
+open(99, file="test.inp")
+write(99, '(a)') nml_str
+rewind(99)
+read(99,nml=inparm)
+close(99, status="delete")
+
+if (.not.first .or. any (other /= [3,2,1,1])) stop 1
+
+other = 9
+
+open(99, file="test.inp")
+write(99, '(a)') nml_str2
+rewind(99)
+read(99,nml=inparm)
+close(99, status="delete")
+
+if (.not.first .or. any (other /= [3,2,9,9])) stop 2
+
+ints = 66
+
+open(99, file="test.inp", decimal='point')
+write(99, '(a)') str
+rewind(99)
+read(99,*) ints
+close(99, status="delete")
+
+if (any (ints /= [1,2,3,4,5,66])) stop 3
+
+ints = 77 
+
+open(99, file="test.inp", decimal='comma')
+write(99, '(a)') str2
+rewind(99)
+read(99,*) ints
+close(99, status="delete")
+
+if (any (ints /= [1,2,3,4,5,77])) stop 4
+end
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index b56f2a4e6d6..5bbbef26c26 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -463,7 +463,7 @@ eat_separator (st_parameter_dt *dtp)
 
   dtp->u.p.comma_flag = 0;
   c = next_char (dtp);
-  if (c == ' ')
+  if (c == ' ' || c == '\t')
 {
   eat_spaces (dtp);
   c = next_char (dtp);


Re: [patch, libgfortran] PR114304 - [13/14 Regression] libgfortran I/O – bogus "Semicolon not allowed as separator with DECIMAL='point'"

2024-04-05 Thread Tobias Burnus

Hi Jerry, hello world,

Jerry D wrote:

On 4/5/24 10:47 AM, Jerry D wrote:

On 4/4/24 2:41 PM, Tobias Burnus wrote:
I think for the current testcases, I like the patch – the question 
is only what's about:

   ',3' as input for 'comma'   (or '.3' as input for 'point')
[...]
But for 'comma': [...]
* GCC with your patch: Same result: ios != 0 and nothing read.

Expected: [...] read-in value is 0.3. [...]



See attached updated patch.
Regressions tested on x86-64. OK for trunk and 13 after a bit.


OK. Thanks for the patch!

Tobias



Re: [patch, libgfortran] PR114304 - [13/14 Regression] libgfortran I/O – bogus "Semicolon not allowed as separator with DECIMAL='point'"

2024-04-04 Thread Tobias Burnus

Hi Jerry,

I think for the current testcases, I like the patch – the question is 
only what's about:


  ',3' as input for 'comma'   (or '.3' as input for 'point')

For 'point' – 0.3 is read and ios = 0 (as expected)
But for 'comma':
* GCC 12 reads nothing and has ios = 0.
* GCC 13/mainline has an error (ios != 0 – and reads nothing)
* GCC with your patch: Same result: ios != 0 and nothing read.

Expected: Same as with ','/'comma' – namely: read-in value is 0.3.
→ https://godbolt.org/z/4rc8fz4sT for the full example, which works with 
ifort, ifx and flang


* * *

Can you check and fix this? It looks perfectly valid to me to have 
remove the '0' in the floating point numbers '0.3' or '0,3' seems to be 
permitted – and it works for '.' (with 'point') but not for ',' (with 
'comma').


F2023's "13.10.3.1 List-directed input forms" refers to "13.7.2.3.2 F 
editing", which states:


"The standard form of the input field [...] The form of the mantissa is 
an optional sign, followed by a string of one or more digits optionally 
containing a decimal symbol."


The latter does not require that the digit has to be before the decimal 
sign and as for output, it is optional, it is surely intended that ",3" 
is a valid floating-point number for decimal='comma'.


* * *

I extended the testcase to check for this – see attached diff. All 
'point' work, all 'comma' fail.


Thanks for working on this!

Tobiasdiff --git a/gcc/testsuite/gfortran.dg/pr114304.f90 b/gcc/testsuite/gfortran.dg/pr114304.f90
index 8344a9ea857..2bcf9bc7f57 100644
--- a/gcc/testsuite/gfortran.dg/pr114304.f90
+++ b/gcc/testsuite/gfortran.dg/pr114304.f90
@@ -70,7 +70,25 @@
   call t(.true.,  'point', '4,4 ,', .true.)
   call t(.true.,  'comma', '4;4 ;', .true.)
   call t(.true.,  'point', '4,4 ;', .true.)
+
+  call t2('comma', ',2')
+  call t2('point', '.2')
+  call t2('comma', ',2;')
+  call t2('point', '.2,')
+  call t2('comma', ',2 ,')
+  call t2('point', '.2 .')
 contains
+subroutine t2(dec, testinput)
+  character(*) :: dec, testinput
+  integer ios
+  real :: r
+  r = 42
+  read(testinput,*,decimal=dec,iostat=ios) r
+  if (ios /= 0 .or.  abs(r - 0.2) > epsilon(r)) then
+print '(*(g0))', dec, ', testinput = "',testinput,'"',', r=',r,' ios=',ios
+stop 3 
+  end if
+end
 subroutine t(valid, dec, testinput, isreal)
   logical, value :: valid
   character(len=*) :: dec, testinput


Re: [patch, libgfortran] PR114304 - [13/14 Regression] libgfortran I/O – bogus "Semicolon not allowed as separator with DECIMAL='point'"

2024-04-04 Thread Tobias Burnus

Hi Jerry,

Jerry D wrote:
The attached log entry and patch (git show) fixes this issue by adding 
logic to handle spaces in eat_separators. One or more spaces by 
themselves are a valid separator. So in this case we look at the 
character following the spaces to see if it is a comma or semicolon.


If so, I change it to the valid separator for the given decimal mode, 
point or comma. This allows the comma or semicolon to be interpreted as 
a null read on the next effective item in the formatted read.


I chose a permissive approach here that allows reads to proceed when the
input line is mal-formed with an incorrect separator as long as there is 
at least one space in front of it.


First: Consider also adding 'PR fortran/105473' to the commit log
as the PRs are closely related, albeit this PR is different-

The patch looks mostly like I would expect, except for decimal='point' 
and a ';' which is *not* preceded by a space.


Thanks for working on it.

Regarding the 'except' case:

* * *

If I try your patch with the testcase of at comment 19,

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114304#c19
→ https://gcc.gnu.org/bugzilla/attachment.cgi?id=57695 ,

I do note that with 'decimal=point', a tailing semicolon is silently
accepted – even if not proceeded by a space.

I think such code is invalid – and you could consider to reject it.
Otherwise, the handling all seems to be in line with the Fortran spec.

i.e. for the following string, I had *expected an error*:

 point, isreal =  F , testinput = ";"n=  42  ios=   0
 point, isreal =  F , testinput = "5;"n=   5  ios=   0
 point, isreal =  T , testinput = "8;"r=   8.  ios= 0
 point, isreal =  T , testinput = "3.3;"r=   3.2995  ios= 0
 point, isreal =  T , testinput = "3,3;"r=   3.  ios= 0

while I think the following is OK (i.e. no error is what I expect) due 
to the the space before the ';'.


 point, isreal =  F , testinput = "7 ;"n=   7  ios= 0
 point, isreal =  T , testinput = "9 ;"r=   9.  ios= 0
 point, isreal =  T , testinput = "4.4 ;"r=   4.4010  ios=0
 point, isreal =  T , testinput = "9 ;"r=   9.  ios= 0
 point, isreal =  T , testinput = "4,4 ;"r=   4.  ios= 0

* * *

Looking at the other compilers, ifort, ifx and Flang do issue an error 
here. Likewise, g95 seems to yield an error in this case (see below).


I do note that the Lapack testcase that triggered this PR did have such 
a code - but it was then changed because g95 did not like it:


https://github.com/Reference-LAPACK/lapack/commit/64e8a7500d817869e5fcde35afd39af8bc7a8086

In terms of gfortran: until recently did accept it (all versions, 
including 13+14); it then rejected it due to the change in PR105473 (GCC 
14/mainline, backported to 13)– but I now think it rightly did so. With 
the current patch, it is accepted again.


* * *

I have attached the modified testcase linked above; consider adding it 
as well. - Changes to the one of the attachment:

- I added a few additional (albeit boring) tests
- I added an expected output + error diagnostic.

The testcase assumes an error for ';' as separator (with 'point'), 
unless there is a space before it.


[If we want to not diagnose this as vendor extension, we really need to 
add a comment to that testcase besides changing valid = .false. to .true.]


Tobias! { dg-do run }
!
! PR fortran/114304
!
! See also PR fortran/105473
!
! Testing: Does list-directed reading an integer/real allows some non-integer input?
!
! Note: GCC result comments before fix of this PR.

  implicit none
  call t(.true.,  'comma', ';') ! No error shown
  call t(.false., 'point', ';') ! /!\ gfortran: no error, others: error
  call t(.false., 'comma', ',') ! Error shown
  call t(.true.,  'point', ',') ! No error shown
  call t(.false., 'comma', '.') ! Error shown
  call t(.false., 'point', '.') ! Error shown
  call t(.false., 'comma', '5.') ! Error shown
  call t(.false., 'point', '5.') ! gfortran/flang: Error shown, ifort: no error
  call t(.false., 'comma', '5,') ! gfortran: error; others: no error
  call t(.true.,  'point', '5,') ! No error shown
  call t(.true.,  'comma', '5;') ! No error shown
  call t(.false., 'point', '5;') ! /!\ gfortran: no error shown, others: error
  call t(.true.,  'comma', '7 .') ! No error shown
  call t(.true.,  'point', '7 .') ! No error shown
  call t(.true.,  'comma', '7 ,') ! /!\ gfortran: error; others: no error
  call t(.true.,  'point', '7 ,') ! No error shown
  call t(.true.,  'comma', '7 ;') ! No error shown
  call t(.true.,  'point', '7 ;') ! No error shown

!  print *, '---'

  call t(.false., 'comma', '8.', .true.) ! Error shown
  call t(.true.,  'point', '8.', .true.) ! gfortran/flang: Error shown, ifort: no error
  call t(.true.,  'comma', '8,', .true.) ! gfortran: error; others: no error
  call t(.true.,  'point', '8,', .true.) ! No error shown
  call t(.true.,  'comma', '8;', .true.) ! No 

Re: OpenACC 2.7: front-end support for readonly modifier: Add basic OpenACC 'declare' testing

2024-03-14 Thread Tobias Burnus

Hi all, hi Thomas & Chung-Lin,

Thomas Schwinge wrote:

But I realized another thing: don't we have to handle the 'readonly'
modifier also in Fortran module files, that is, next to the OpenACC
'declare' 'copyin' handling in 'gcc/fortran/module.cc':
'AB_OACC_DECLARE_COPYIN' etc.?


I bet so; it is not as bad as with the others as it is "only" an 
optimization hint, but it makes sense to make it available.


Note that when you place the 'module' in the same file as the module 
users ('use'), the compiler might know things because they are in the 
same translation unit / file not because it is in the module ...



  Chung-Lin, please check, via test cases.
'gfortran.dg/goacc/routine-module*', for example, should provide some
guidance of how to achieve actual module file use, and then do the same
'scan-tree-dump' as in the current 'readonly' modifier test cases.

...

By means of only emitting a tag
in the module file if the 'readonly' modifier is specified, we should
maintain compatibility with the current 'MOD_VERSION'.


That was the idea: If only new information gets added (if used), older 
compilers still work. This has huge limitations and does not work as 
well as imagined but here it should work: Older .mod will work with new 
compilers, even though the reverse might not be true.


Tobias


Re: OpenACC 2.7: front-end support for readonly modifier: Add basic OpenACC 'declare' testing

2024-03-14 Thread Tobias Burnus

Hi all, hi Thomas & Chung-Lin,

Thomas Schwinge wrote:

But I realized another thing: don't we have to handle the 'readonly'
modifier also in Fortran module files, that is, next to the OpenACC
'declare' 'copyin' handling in 'gcc/fortran/module.cc':
'AB_OACC_DECLARE_COPYIN' etc.?


I bet so; it is not as bad as with the others as it is "only" an
optimization hint, but it makes sense to make it available.

Note that when you place the 'module' in the same file as the module
users ('use'), the compiler might know things because they are in the
same translation unit / file not because it is in the module ...


  Chung-Lin, please check, via test cases.
'gfortran.dg/goacc/routine-module*', for example, should provide some
guidance of how to achieve actual module file use, and then do the same
'scan-tree-dump' as in the current 'readonly' modifier test cases.

...

By means of only emitting a tag
in the module file if the 'readonly' modifier is specified, we should
maintain compatibility with the current 'MOD_VERSION'.


That was the idea: If only new information gets added (if used), older
compilers still work. This has huge limitations and does not work as
well as imagined but here it should work: Older .mod will work with new
compilers, even though the reverse might not be true.

Tobias


Re: [PATCH, OpenACC 2.7] struct/array reductions for Fortran

2024-03-13 Thread Tobias Burnus

Hi Chung-Lin, hi Thomas, hello world,

some thoughts glancing at the patch.

Chung-Lin Tang wrote:

There is still some shortcomings in the current state, mainly that only explicit-shaped 
arrays can be used (like its C counterpart). Anything else is currently a bit more 
complicated in the middle-end, since the existing reduction code creates an 
"init-op" (literal of initial values) which can't be done when say 
TYPE_MAX_VALUE (TYPE_DOMAIN (array_type)) is not a tree constant. I think we'll be on the 
hook to solve this later, but I think the current state is okay to submit.


I think having some initial support is fine, but it needs an 
understandable and somewhat complete error diagnostic and testcases. 
More to this below.



+  if (!TREE_CONSTANT (min_tree) || !TREE_CONSTANT (max_tree))
+   {
+ error_at (loc, "array in reduction must be of constant size");
+ return error_mark_node;
+   }

Shouldn't this use a sorry_at instead?


+ /* OpenACC current only supports array reductions on explicit-shape
+arrays.  */
+ if ((n->sym->as && n->sym->as->type != AS_EXPLICIT)
+ || n->sym->attr.codimension)
gfc_error ("Array %qs is not permitted in reduction at %L",
   n->sym->name, >where);
[Coarray excursion. I am in favor of allowing it for the reasons above, 
but it could be also rejected but I would prefer to have a proper error 
message in that case.]


While coarrays are unspecified, I do not see a reason why a corray 
shouldn't be permitted here – as long as it is not coindexed. At the 
end, it is just a normal array with some additional properties, which 
make it possible to remotely access it.


Note: For coarray scalars, we have 'sym->as', thus the check should be 
'(n->sym->as && n->sym->as->rank)' to permit scalar coarrays.


* * *

Coarray excursion: A coarray variables exists in multiple processes 
("images", e.g. MPI processes). If 'caf' and 'caf2' are coarrays, then 
'caf = 5' and 'i = caf2' refer to the local variable.


On the other hand, 'caf[n] = 5' or 'i = caf[3,m]' refers to the 'caf' 
variable on image 'n' or [3,m]', respectively, which implies in general 
some function call to read or set the remote data, unless the memory is 
directly accessible (→ e.g. some offset calculation) and the compiler 
already knows how to handle this.


While a coarrary might be allocated in some special memory, as long as 
one uses the local version (i.e. not coindexed / without the image index 
in brackets).


Assume for the example above, e.g., integer :: caf[*], caf2[3:6, 7:*].

* * *

Thus, in terms of OpenACC or OpenMP, there is no reason to fret a 
coarray as long as it is not coindexed and as long as OpenMP/OpenACC 
does not interfere with the memory allocation – either directly ('!$omp 
allocators') or indirectly by placing it into special memory (pinned, 
pseudo-unified-shared memory → OG13's -foffload-memory=pinned/unified).


In the meanwhile, OpenMP actually explicitly allows coarrays with few 
exceptions while OpenACC talks about unspecified behavior.


* * *

Back to generic comments:

If I look at the existing code, I see at gfc_match_omp_clause_reduction:


 if (gfc_match_omp_variable_list (" :", >lists[list_idx], false, NULL,
  , openacc, allow_derived) != 
MATCH_YES)


If 'openacc' is true, array sections are permitted - but the code added 
(see quote above) does not handle n->expr at all and only n->sym.


I think there needs to be at least a "gfc_error ("Sorry, subarrays/array 
sections not yet handled" [subarray is the OpenACC wording, 'array 
section' is the Fortran one, which might be clearer.


But you could consider to handle at least array elements, i.e. 
n->expr->rank == 0.


Additionally, I think the current error message is completely unhelpful 
given that some arrays are supported but most are not.


I think there should be also some testcases for the not-yet-supported 
case. I think the following will trigger the omp-low.cc 'sorry_at' (or 
currently 'error' - but I think it should be a sorry):


subroutine foo(n)

integer :: n, A(n)

... reduction(+:A)

And most others will trigger in openmp.cc; for those, you should have an 
allocatable/pointer and assumed-shape arrays for the diagnostic testcase 
as well.


* * *

I have not really experimented with the code, but does it handle 
multi-dimensional constant arrays like 'integer :: a(3:6,10,-1:1)' ? — I 
bet it does, at least after handling my example [2] for the C patch [1].


Thanks,

Tobias

[1] https://gcc.gnu.org/pipermail/gcc-patches/2024-January/641669.html

[2] https://gcc.gnu.org/pipermail/gcc-patches/2024-March/647704.html



Re: [Patch] OpenMP/Fortran: Fix defaultmap(none) issue with dummy procedures [PR114283]

2024-03-12 Thread Tobias Burnus

Jakub Jelinek wrote:


So firstprivate clause handling remaps them then if declare target indirect
is used? If so, the patch looks reasonable to me.


[I have now updated the patch to turn the testcase to ensure
that is also keeps works at runtime.]

OpenMP leaves it a bit open when the remapping has to happen,
but one can construct cases – in particular with unified-shared memory –
where it is not possible to do this upon entry to a target region.

Thus, it has to be done when the function is invoked, e.g.

i = (*g) ();

is turned (in the target region but only on the device side) into

i = (*GOMP_target_map_indirect_ptr (g)) ();

Thus, as long as the host pointer value is transferred to the device,
it works – as the lookup is done on the device side. Directly using a
device address (remap when mapping to the target) will also not shorten
the lookup, i.e. there is no need for it.

Does it still look reasonable to you?

Tobias

PS: The current OpenMP specification, it is listed mainly described via
the glossary (newest change is the addition of dummy procedure):

"indirect device invocation – An indirect call to the _device_ version of 
a _procedure_ on a _device_ other than the _host-device_, through a 
function pointer (C/C++), a pointer to a member function (C++), a dummy 
procedure (Fortran), or a procedure pointer (Fortran) that refers to the 
host version of the _procedure_."
OpenMP/Fortran: Fix defaultmap(none) issue with dummy procedures [PR114283]

Dummy procedures look similar to variables but aren't - neither in Fortran
nor in OpenMP. As the middle end sees PARM_DECLs, mark them as predetermined
firstprivate for mapping (as already done in gfc_omp_predetermined_sharing).

This does not address the isses related to procedure pointers, which are
still discussed on spec level [see PR].

	PR fortran/114283

gcc/fortran/ChangeLog:

	* trans-openmp.cc (gfc_omp_predetermined_mapping): Map dummy
	procedures as firstprivate.

libgomp/ChangeLog:

	* testsuite/libgomp.fortran/declare-target-indirect-4.f90: New test.

 gcc/fortran/trans-openmp.cc|  9 +
 .../libgomp.fortran/declare-target-indirect-4.f90  | 43 ++
 2 files changed, 52 insertions(+)

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index a2bf15665b3..1dba47126ed 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -343,6 +343,15 @@ gfc_omp_predetermined_mapping (tree decl)
 	&& GFC_DECL_SAVED_DESCRIPTOR (decl)))
 return OMP_CLAUSE_DEFAULTMAP_TO;
 
+  /* Dummy procedures aren't considered variables by OpenMP, thus are
+ disallowed in OpenMP clauses.  They are represented as PARM_DECLs
+ in the middle-end, so return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE here
+ to avoid complaining about their uses with defaultmap(none).  */
+  if (TREE_CODE (decl) == PARM_DECL
+  && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
+  && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
+return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
+
   /* These are either array or derived parameters, or vtables.  */
   if (VAR_P (decl) && TREE_READONLY (decl)
   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
diff --git a/libgomp/testsuite/libgomp.fortran/declare-target-indirect-4.f90 b/libgomp/testsuite/libgomp.fortran/declare-target-indirect-4.f90
new file mode 100644
index 000..43f4295494c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/declare-target-indirect-4.f90
@@ -0,0 +1,43 @@
+! { dg-additional-options "-fdump-tree-gimple" }
+
+! PR fortran/114283
+
+! { dg-final { scan-tree-dump "#pragma omp parallel shared\\(i\\) if\\(0\\) default\\(none\\) firstprivate\\(g\\)" "gimple" } }
+! { dg-final { scan-tree-dump "#pragma omp target num_teams\\(-2\\) thread_limit\\(0\\) firstprivate\\(h\\) map\\(from:j \\\[len: 4\\\]\\) defaultmap\\(none\\)" "gimple" } }
+
+
+module m
+  implicit none (type, external)
+  !$omp declare target indirect enter(f1, f2)
+contains
+  integer function f1 ()
+f1 = 99
+  end
+  integer function f2 ()
+f2 = 89
+  end
+end module m
+
+use m
+implicit none (type, external)
+call sub1(f1)
+call sub2(f2)
+contains
+  subroutine sub1(g)
+procedure(integer) :: g
+integer :: i
+!$omp parallel default(none) if(.false.) shared(i)
+  i = g ()
+!$omp end parallel
+if (i /= 99) stop 1
+  end
+
+  subroutine sub2(h)
+procedure(integer) :: h
+integer :: j
+!$omp target defaultmap(none) map(from:j)
+  j = h ()
+!$omp end target
+if (j /= 89) stop 1
+  end
+end


[Patch] OpenMP/Fortran: Fix defaultmap(none) issue with dummy procedures [PR114283]

2024-03-11 Thread Tobias Burnus

Using dummy procedures in a target region with 'defaultmap(none)' leads to:

  Error: 'g' not specified in enclosing 'target'

and this cannot be fixed by using 'firstprivate' as non-pointer dummy routines
are rejected as "Error: Object 'g' is not a variable".

Fixed by doing the same for mapping as for data sharing: using predetermined
firstprivate.

BTW: Only since GCC 14, 'declare target indirect' makes it possible to
simply use dummy procedures and procedures pointers in a target region.

Comments? Suggestions?

Tobias

PS: Procedure pointers aren't variables either, but they act even more like
variables as they permit changing pointer association such that '(first)private'
vs. 'shared'/'map' can both make sense. — GCC accepts those in (nearly) all 
clauses,
ifort only in (first)private while flang not at all. The spec is somewhat silent
about it. This is tracked in the same PR (PR114283) and in the specification
issue #3823.
OpenMP/Fortran: Fix defaultmap(none) issue with dummy procedures [PR114283]

Dummy procedures look similar to variables but aren't - neither in Fortran
nor in OpenMP. As the middle end sees PARM_DECLs, mark them as predetermined
firstprivate for mapping (as already done in gfc_omp_predetermined_sharing).

This does not address the isses related to procedure pointers, which are
still discussed on spec level [see PR].

	PR fortran/114283

gcc/fortran/ChangeLog:

	* trans-openmp.cc (gfc_omp_predetermined_mapping): Map dummy
	procedures as firstprivate.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/target4.f90: New test.

 gcc/fortran/trans-openmp.cc|  9 +
 gcc/testsuite/gfortran.dg/gomp/target4.f90 | 18 ++
 2 files changed, 27 insertions(+)

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index a2bf15665b3..1dba47126ed 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -343,6 +343,15 @@ gfc_omp_predetermined_mapping (tree decl)
 	&& GFC_DECL_SAVED_DESCRIPTOR (decl)))
 return OMP_CLAUSE_DEFAULTMAP_TO;
 
+  /* Dummy procedures aren't considered variables by OpenMP, thus are
+ disallowed in OpenMP clauses.  They are represented as PARM_DECLs
+ in the middle-end, so return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE here
+ to avoid complaining about their uses with defaultmap(none).  */
+  if (TREE_CODE (decl) == PARM_DECL
+  && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
+  && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
+return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
+
   /* These are either array or derived parameters, or vtables.  */
   if (VAR_P (decl) && TREE_READONLY (decl)
   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
diff --git a/gcc/testsuite/gfortran.dg/gomp/target4.f90 b/gcc/testsuite/gfortran.dg/gomp/target4.f90
new file mode 100644
index 000..09364e707f1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target4.f90
@@ -0,0 +1,18 @@
+! { dg-additional-options "-fdump-tree-gimple" }
+
+! PR fortran/114283
+
+! { dg-final { scan-tree-dump "#pragma omp parallel default\\(none\\) firstprivate\\(g\\)" "gimple" } }
+! { dg-final { scan-tree-dump "#pragma omp target num_teams\\(-2\\) thread_limit\\(0\\) defaultmap\\(none\\) firstprivate\\(g\\)" "gimple" } }
+
+subroutine f(g)
+procedure() :: g
+
+!$omp parallel default(none)
+  call g
+!$omp end parallel
+
+!$omp target defaultmap(none)
+  call g
+!$omp end target
+end


[Patch] Fortran/Openmp: Use OPT_Wopenmp for gfc_match_omp_depobj warning

2024-02-23 Thread Tobias Burnus
When checking something else, I noticed that there was one warning in 
openmp.cc that did not use OPT_Wopenmp.


I intent to commit the attached patch later today as obvious.

Tobias
Fortran/Openmp: Use OPT_Wopenmp for gfc_match_omp_depobj warning

gcc/fortran/ChangeLog:

	* openmp.cc (gfc_match_omp_depobj): Use OPT_Wopenmp
	as warning category in gfc_warning.

 gcc/fortran/openmp.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 77f6e1732f9..38de60238c0 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -4768,8 +4768,8 @@ gfc_match_omp_depobj (void)
   if (gfc_match (" ( %v ) ", ) == MATCH_YES)
 	{
 	  if (destroyobj->symtree != depobj->symtree)
-	gfc_warning (0, "The same depend object should be used as DEPOBJ "
-			 "argument at %L and as DESTROY argument at %L",
+	gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
+			 " DEPOBJ argument at %L and as DESTROY argument at %L",
 			 >where, >where);
 	  gfc_free_expr (destroyobj);
 	}


Re: [PATCH v2] openmp, fortran: Add Fortran support for indirect clause on the declare target directive

2024-02-12 Thread Tobias Burnus

Hi Kwok,

Kwok Cheung Yeung wrote:
Oops. I thought exactly the same thing yesterday, but forgot to add 
the changes to my commit! Here is the updated version.


I regard(ed) this change as obvious - hence, I missed to reply.
But for completeness: LGTM.

I think it would be useful to commit this now with an xfail
for the one failing testcase that depends on the review-pending libgomp
patch.

I mean something like:

--- a/libgomp/testsuite/libgomp.fortran/declare-target-indirect-2.f90
+++ b/libgomp/testsuite/libgomp.fortran/declare-target-indirect-2.f90
@@ -1,2 +1,3 @@
 ! { dg-do run }
+! { dg-xfail-run-if "Requires libgomp bug fix pending review" { offload_device 
} }

Thanks,

Tobias


On 06/02/2024 9:03 am, Tobias Burnus wrote:
LGTM. I just wonder whether there should be a value test and not just 
a does-not-crash-when-called test for the latter testcase, i.e.




+++ b/libgomp/testsuite/libgomp.fortran/declare-target-indirect-3.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+
+! Check that indirect calls work on procedures passed in via a 
dummy argument

+
+module m
+contains
+  subroutine bar
+    !$omp declare target enter(bar) indirect

e.g. "integer function bar()" ... " bar = 42"

+  end subroutine
+
+  subroutine foo(f)
+    procedure(bar) :: f
+
+    !$omp target
+  call f

And then: if (f() /= 42) stop 1

+    !$omp end target
+  end subroutine
+end module


Thanks,

Tobias



Re: [PATCH v2] openmp, fortran: Add Fortran support for indirect clause on the declare target directive

2024-02-06 Thread Tobias Burnus

Kwok Cheung Yeung wrote:
As previously discussed, this version of the patch adds code to emit a 
warning when a directive like this:


!$omp declare target indirect(.true.)

is encountered (i.e. a target directive containing at least one 
clause, but no to/enter clause, which appears to violate the OpenMP 
standard). A test is also added to 
gfortran.dg/gomp/declare-target-indirect-1.f90 to test for this.


Thanks. And indeed, the 5.1 spec requires under "Restrictions to the 
declare target directive are as follows:" "If the directive has a 
clause, it must contain at least one 'to' clause or at least one 'link' 
clause.". [5.2 replaced 'to' by its alias 'enter' and the 6.0 preview 
added 'local' to the list.]



I have also added a declare-target-indirect-3.f90 test to libgomp to 
check that procedures passed via a dummy argument work properly when 
used in an indirect call.


Okay for mainline?


LGTM. I just wonder whether there should be a value test and not just a 
does-not-crash-when-called test for the latter testcase, i.e.




+++ b/libgomp/testsuite/libgomp.fortran/declare-target-indirect-3.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+
+! Check that indirect calls work on procedures passed in via a dummy argument
+
+module m
+contains
+  subroutine bar
+!$omp declare target enter(bar) indirect

e.g. "integer function bar()" ... " bar = 42"

+  end subroutine
+
+  subroutine foo(f)
+procedure(bar) :: f
+
+!$omp target
+  call f

And then: if (f() /= 42) stop 1

+!$omp end target
+  end subroutine
+end module


Thanks,

Tobias


Re: [PATCH] openmp, fortran: Add Fortran support for indirect clause on the declare target directive

2024-01-23 Thread Tobias Burnus

Kwok Cheung Yeung wrote:
This patch adds support for the indirect clause on the OpenMP 'declare 
target' directive in Fortran. As with the C and C++ front-ends, this 
applies the 'omp declare target indirect' attribute on affected 
function declarations. The C test cases have also been translated to 
Fortran where appropriate.


Okay for mainline?


LGTM – can you also update the following libgomp.texi entry?

@item @code{indirect} clause in @code{declare target} @tab P @tab Only C 
and C++


Thanks,

Tobias



Re: Open MP offloading

2024-01-11 Thread Tobias Burnus

Hi,

Rheinhardt Matthias wrote:
at the moment, offloading Open MP workshare section is not supported, 
nor can implicit do-loops from expressions with array syntax be delt 
with in another way for offloading. Are there any plannings to lift this 
restriction, which is rather severe for - in particular scientific - 
Fortran codes?


I think the real solution is 'coexecute' that can also be used as 
'target teams coexecute'.


However, 'coexecute' was only added to the second preview of OpenMP 
(TR/Technical Report 12); thus, it will take a while until it is 
implemented and even longer until compiler produce optimized code. The 
first preview of OpenMP 6.0 was released in November 2022, TR12 last 
November and the final OpenMP 6.0 is expected for this November (2024).


The TR12 specification can be found at 
https://www.openmp.org/specifications/ (as can all other OpenMP versions 
and also an a separate document with OpenMP examples).


* * *

With regards to 'workshare', I might miss something but I don't see a 
reason why:


!$omp target
...
 !$omp workshare
 !$omp end workshare
...
!$omp end target

wouldn't work.

* * *

With regards to GCC's OpenMP implementation status, see 
http://gcc.gnu.org/projects/gomp/ – some more items have been 
implemented but still need to be merged (they are in the OG13 / 
devel/omp/gcc-13 vendor branch) or are already work in progress.


GCC 14 is expected to be released in late spring and has currently the 
following new features: https://gcc.gnu.org/gcc-14/changes.html
(release notes not yet fully updated, albeit OpenMP is nearly complete) 
- note that certain features like memory management (like whether 
pinning supported etc.) do not show up in the list above as a compliant 
implementation does not have to support it; those get mentioned in the 
release notes and more details can be found in the manual.


For GCC 15, I hope to see a full support of OpenMP 5.x (x=0,1,2), but 
essentially no OpenMP 6 features like 'coexecute'.


Thanks,

Tobias


Re: [PATCH 2/8] OpenMP: lvalue parsing for map/to/from clauses (C)

2024-01-10 Thread Tobias Burnus

Julian Brown wrote:

This patch adds support for parsing general lvalues ("locator list item
types") for OpenMP "map", "to" and "from" clauses to the C front-end,
similar to the previously-posted patch for C++.  Such syntax is permitted
for OpenMP 5.0 and above.  It was previously posted for mainline here


...

In libgomp/libgomp.texi, the following can now be set to 'Y':

@item C/C++'s lvalue expressions in @code{to}, @code{from}
  and @code{map} clauses @tab N @tab


@@ -11253,16 +11263,41 @@ c_parser_postfix_expression_after_primary (c_parser 
*parser,
case CPP_OPEN_SQUARE:
  /* Array reference.  */
  c_parser_consume_token (parser);
- idx = c_parser_expression (parser).value;
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-"expected %<]%>");
- start = expr.get_start ();
- finish = parser->tokens_buf[0].location;
- expr.value = build_array_ref (op_loc, expr.value, idx);
- set_c_expr_source_range (, start, finish);
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- expr.m_decimal = 0;
+ idx = len = NULL_TREE;
+ if (!c_omp_array_section_p
+ || c_parser_next_token_is_not (parser, CPP_COLON))
+   idx = c_parser_expression (parser).value;
+
+ if (c_omp_array_section_p
+ && c_parser_next_token_is (parser, CPP_COLON))
+   {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
+   len = c_parser_expression (parser).value;
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+"expected %<]%>");
+
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].location;
+ expr.value = build_omp_array_section (op_loc, expr.value, idx,
+   len);
+ set_c_expr_source_range (, start, finish);
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+   }
+ else
+   {
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+"expected %<]%>");
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].location;
+ expr.value = build_array_ref (op_loc, expr.value, idx);
+ set_c_expr_source_range (, start, finish);
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ expr.m_decimal = 0;
+   }


I think that's more readable when moving everything but the expr.value 
assignment after the if/else (obviously for "if" also everything until 
"len =" has to remain). That also adds the missing "m_decimal = 0" for 
the "if" case.



@@ -13915,8 +13955,97 @@ c_parser_omp_variable_list (c_parser *parser,

...

+ else if (TREE_CODE (decl) == INDIRECT_REF)
+   {
+ /* Turn *foo into the representation previously used for
+foo[0].  */
+ decl = TREE_OPERAND (decl, 0);
+ STRIP_NOPS (decl);
+
+ decl = build_omp_array_section (loc, decl, integer_zero_node,
+ integer_one_node);
+   }


I wonder whether we shouldn't use the C++ wording, i.e.

  /* If we have "*foo" and
 - it's an indirection of a reference, "unconvert" it,
   i.e. strip the indirection (to just "foo").
 - it's an indirection of a pointer, turn it into
   "foo[0:1]".  */

* * *

As remarked for cp/typecheck.cc's build_omp_array_section:


+tree
+build_omp_array_section (location_t loc, tree array, tree index, tree length)
+{
+  tree idxtype;
+
+  if (index != NULL_TREE
+  && length != NULL_TREE
+  && INTEGRAL_TYPE_P (TREE_TYPE (index))
+  && INTEGRAL_TYPE_P (TREE_TYPE (length)))
+{
+  tree low = fold_convert (sizetype, index);
+  tree high = fold_convert (sizetype, length);
+  high = size_binop (PLUS_EXPR, low, high);
+  high = size_binop (MINUS_EXPR, high, size_one_node);
+  idxtype = build_range_type (sizetype, low, high);
+}
+  else if ((index == NULL_TREE || integer_zerop (index))
+  && length != NULL_TREE
+  && INTEGRAL_TYPE_P (TREE_TYPE (length)))
+idxtype = build_index_type (length);
+  else
+idxtype = NULL_TREE;
+
+  tree type = TREE_TYPE (array);
+  gcc_assert (type);
+
+  tree sectype, eltype = TREE_TYPE (type);
+
+  /* It's not an array or pointer type.  Just reuse the type of the original
+ expression as the type of the array section (an error will be raised
+ anyway, later).  */
+  if (eltype == NULL_TREE
+  || error_operand_p (eltype)
+  || error_operand_p (idxtype))
+sectype = TREE_TYPE (array);
+  else
+sectype = 

Re: [PATCH 1/8] OpenMP: lvalue parsing for map/to/from clauses (C++)

2024-01-07 Thread Tobias Burnus

Am 05.01.24 um 13:23 schrieb Julian Brown:

On Wed, 20 Dec 2023 15:31:15 +0100
Tobias Burnus  wrote:
Here's a rebased/retested version which fixes those bits (I haven't
adjusted the libgomp.texi bit you noted yet, though).

How does this look now?




--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -13499,7 +13499,11 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void 
*data)
   if (TREE_CODE (dtype) == REFERENCE_TYPE)
dtype = TREE_TYPE (dtype);
   /* FIRSTPRIVATE_POINTER doesn't work well if we have a
-multiply-indirected pointer.  */
+multiply-indirected pointer.  If we have a reference to a pointer to
+a pointer, it's possible that this should really be
+GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
+moment, so stick with this.  (See testcase
+baseptrs-4.C:ref2ptrptr_offset_decl_member_slice).  */


Looks as we should have a tracking PR about this; can you file one?

* * *


+  if (processing_template_decl)
+{
+  if (type_dependent_expression_p (array_expr)
+ || type_dependent_expression_p (index)
+ || type_dependent_expression_p (length))
+   return build_min_nt_loc (loc, OMP_ARRAY_SECTION, array_expr, index,
+length);
+}


I personally find it more readable if combined in a single 'if' condition.


+ /* Turn *foo into foo[0:1].  */
+ decl = TREE_OPERAND (decl, 0);
+ STRIP_NOPS (decl);
+
+ /* If we have "*foo" and
+- it's an indirection of a reference, "unconvert" it, i.e.
+  strip the indirection (to just "foo").
+- it's an indirection of a pointer, turn it into
+  "foo[0:1]".  */
+ if (!ref_p)
+   decl = grok_omp_array_section (loc, decl, integer_zero_node,
+  integer_one_node);


I would remove the first comment and remove the two succeeding lines 
below the second comment.




+ /* This code rewrites a parsed expression containing various tree
+codes used to represent array accesses into a more uniform nest of
+OMP_ARRAY_SECTION nodes before it is processed by
+semantics.cc:handle_omp_array_sections_1.  It might be more
+efficient to move this logic to that function instead, analysing
+the parsed expression directly rather than this preprocessed
+form.  */


Or to do this transformation in handle_omp_array_sections to get still a 
unified result in the middle end. I see advantages of all three 
solutions. (Doing this in parse.cc (as currently done) feels a bit odd, 
though.)


* * *


build_omp_array_section (location_t loc, tree array_expr, tree index,
+tree length)
+{
+  tree idxtype;
+
+  /* If we know the integer bounds, create an index type with exact
+ low/high (or zero/length) bounds.  Otherwise, create an incomplete
+ array type.  (This mostly only affects diagnostics.)  */
+  if (index != NULL_TREE
+  && length != NULL_TREE
+  && TREE_CODE (index) == INTEGER_CST
+  && TREE_CODE (length) == INTEGER_CST)
+{
+  tree low = fold_convert (sizetype, index);
+  tree high = fold_convert (sizetype, length);
+  high = size_binop (PLUS_EXPR, low, high);
+  high = size_binop (MINUS_EXPR, high, size_one_node);
+  idxtype = build_range_type (sizetype, low, high);
+}
+  else if ((index == NULL_TREE || integer_zerop (index))
+  && length != NULL_TREE
+  && TREE_CODE (length) == INTEGER_CST)
+idxtype = build_index_type (length);
+  else
+idxtype = NULL_TREE;
+
+  tree type = TREE_TYPE (array_expr);
+  gcc_assert (type);
+  type = non_reference (type);
+
+  tree sectype, eltype = TREE_TYPE (type);
+
+  /* It's not an array or pointer type.  Just reuse the type of the
+ original expression as the type of the array section (an error will be
+ raised anyway, later).  */
+  if (eltype == NULL_TREE)
+sectype = TREE_TYPE (array_expr);
+  else
+sectype = build_array_type (eltype, idxtype);
+
+  return build3_loc (loc, OMP_ARRAY_SECTION, sectype, array_expr, index,
+length);
+}


I wonder whether it would be more readable if one moves all the 
'idxtype' handling into the last 'else' branch.


* * *

LGTM - please file the PR and consider the readability items above.

Thanks,

Tobias




Re: [PATCH] libgfortran: Bugfix if not define HAVE_ATOMIC_FETCH_ADD

2024-01-03 Thread Tobias Burnus

On 22.12.23 03:36, Lipeng Zhu wrote:

This patch try to fix the bug when HAVE_ATOMIC_FETCH_ADD is
not defined in dec_waiting_unlocked function.

libgfortran/ChangeLog:

  * io/io.h (dec_waiting_unlocked): Use
  __gthread_rwlock_wrlock/__gthread_rwlock_unlock or
  __gthread_mutex_lock/__gthread_mutex_unlock functions
  to replace WRLOCK and RWUNLOCK macros.

Signed-off-by: Lipeng Zhu 


The change looks good to me + I assume it will work, but have not tested
it myself.

Downside is that it slightly breaks with the abstraction done with all
the macros, but it seems to be the simplest solution.

What is really missing - and should be included in the commit message
(before the ChangeLog block) - is the following information:

   As io.h does not include async.h, the WRLOCK and RWUNLOCK macros are
undefined.

(Or something similar in other words.)

I think that helps others when looking at "git log" and wondering *why*
that change was needed.

Thanks,

Tobias


  libgfortran/io/io.h | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 15daa0995b1..c7f0f7d7d9e 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -1020,9 +1020,15 @@ dec_waiting_unlocked (gfc_unit *u)
  #ifdef HAVE_ATOMIC_FETCH_ADD
(void) __atomic_fetch_add (>waiting, -1, __ATOMIC_RELAXED);
  #else
-  WRLOCK (_rwlock);
+#ifdef __GTHREAD_RWLOCK_INIT
+  __gthread_rwlock_wrlock (_rwlock);
+  u->waiting--;
+  __gthread_rwlock_unlock (_rwlock);
+#else
+  __gthread_mutex_lock (_rwlock);
u->waiting--;
-  RWUNLOCK (_rwlock);
+  __gthread_mutex_unlock (_rwlock);
+#endif
  #endif
  }

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH v7 5/5] OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

2023-12-21 Thread Tobias Burnus

Hi Julian,

On 20.12.23 22:29, Julian Brown wrote:

Thanks for review! Here's a new version of the patch which hopefully
addresses this round of comments.


Thanks for the patch. LGTM now.

Tobias


On Tue, 19 Dec 2023 16:41:54 +0100
Tobias Burnus  wrote:


On 16.12.23 14:25, Julian Brown wrote:

--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -10107,6 +10114,20 @@ omp_segregate_mapping_groups
(omp_mapping_group *inlist) ard_tail = >next;
 break;

+ case GOMP_MAP_PRESENT_ALLOC:
+   *pa_tail = w;
+   w->next = NULL;
+   pa_tail = >next;
+   break;
+
+ case GOMP_MAP_PRESENT_FROM:
+ case GOMP_MAP_PRESENT_TO:
+ case GOMP_MAP_PRESENT_TOFROM:
+   *ptf_tail = w;
+   w->next = NULL;
+   ptf_tail = >next;
+   break;
+

First, I note that GOMP_MAP_PRESENT_ALLOC and
GOMP_MAP_PRESENT_{FROM,TO,TOFROM} are semantically identical: If the
variable is not present, error termination will happen - otherwise, if
present, no data movement will happen. Hence, they will be changed to
GOMP_MAP_FORCE_PRESENT in gimplify_adjust_omp_clauses.

That's also the reason that the old code handled all of them
identical.

However, besides a plain 'present', there is also 'always' +
'present'. Those are different as after a normal 'present' check
(abort if not present), the data copying will happen:
GOMP_MAP_ALWAYS_PRESENT_TO, GOMP_MAP_ALWAYS_PRESENT_FROM,
GOMP_MAP_ALWAYS_PRESENT_TOFROM.

(Note that: always + present + alloc = GOMP_MAP_PRESENT_ALLOC (w/o
'always') as already done in the FE.)

Thus, all 'case' from your patch should go to a single group (possibly
adding a comment about it). The question is what to do with the
'present,always' case. I think leaving them under 'default:' is fine,
but I might have missed something.

I've made this change (i.e.: grouping all "GOMP_MAP_PRESENT_*" nodes
together), and in fact that restores the dump output for the
gfortran.dg/gomp/map-12.f90 that needed to be adjusted for the previous
version of the patch (so that hunk has now disappeared).


   default:
 *tf_tail = w;
 w->next = NULL;
@@ -10118,8 +10139,10 @@ omp_segregate_mapping_groups
(omp_mapping_group *inlist)

* * *

@@ -11922,119 +11945,30 @@ gimplify_scan_omp_clauses (tree *list_p,
gimple_seq *pre_p, break;
 }

-  if (code == OMP_TARGET
-  || code == OMP_TARGET_DATA
-  || code == OMP_TARGET_ENTER_DATA
-  || code == OMP_TARGET_EXIT_DATA)
-{
-  vec *groups;
-  groups = omp_gather_mapping_groups (list_p);
-  if (groups)
- {
-   hash_map
*grpmap;
-   grpmap = omp_index_mapping_groups (groups);
+  vec *groups = omp_gather_mapping_groups
(list_p);
+  hash_map *grpmap =
NULL;
+  unsigned grpnum = 0;
+  tree *grp_start_p = NULL, grp_end = NULL_TREE;

...


-  else if (region_type & ORT_ACC)
-{

I wonder whether you should not better call
'omp_gather_mapping_groups' only for the 'code == OMP_TARGET...' and
for ORT_ACC (or some subset of OACC *), given that this function is
also called bygimplify_omp_parallel, gimplify_omp_task,
gimplify_omp_for, ...

This avoids some memory allocation and list_p walking, i.e. it is not
too bad - but also not really needed for task, parallel, for, ...

I've made that change -- OpenACC uses OMP_CLAUSE_MAP in quite a wide
range of directives, but the new version of the patch lists them
individually anyway, rather than using a catch-all for ORT_ACC regions.
That seems OK, I think.


@@ -14008,26 +13926,73 @@ gimplify_adjust_omp_clauses (gimple_seq
*pre_p, gimple_seq body, tree *list_p, default:
 break;
   }
-   if (code == OMP_TARGET_EXIT_DATA
-   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER)
+   switch (code)
   {
+ case OMP_TARGET:
+   break;
+ case OACC_DATA:
+   if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
+ break;
+   goto check_firstprivate;
+ case OACC_ENTER_DATA:
+ case OACC_EXIT_DATA:
+ case OMP_TARGET_DATA:
+ case OMP_TARGET_ENTER_DATA:
+ case OMP_TARGET_EXIT_DATA:
+ case OACC_HOST_DATA:
+ check_firstprivate:
+   if (OMP_CLAUSE_MAP_KIND (c) ==
GOMP_MAP_FIRSTPRIVATE_POINTER

I think it looks nicer if the OACC_HOST is before OMP_* such that all
OACC_* are together. (In the old code, oacc_enter/exit was treated
differently than OMP_* and OACC_HOST_DATA; your order is a leftover
from that code movement/change.)

I've fixed this bit -- which actually doesn't need the goto any more
either, so that's now a fallthrough instead.


+ flags = GOVD_MAP | GOVD_EXPLICIT;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
+   flags |= GOVD_MAP_ALWAYS_TO;

I know that the code has only been moved, but I wonder whether that
should also include GOMP_MAP_ALWAYS_PRESENT_{TO,TOFROM} as condition.

I've a

Re: [PATCH 1/8] OpenMP: lvalue parsing for map/to/from clauses (C++)

2023-12-20 Thread Tobias Burnus

On 05.09.23 21:28, Julian Brown wrote:

This patch supports "lvalue" parsing (or "locator list item type" parsing)
for several OpenMP clause types for C++, as required for OpenMP 5.0
and above.  It is based on the version committed to the og13 branch,
posted here:

   https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623354.html

which in turn was based on the last version posted upstream:

   https://gcc.gnu.org/pipermail/gcc-patches/2022-December/609040.html

This version has mostly just been rebased.


I had a first pass at the patch and didn't spot anything (C++ code wise);
I have some build/rebase issues and one .texi comment that is trivial and
could also be handled together with the 2/8 patch (adding C support).

* * *

Another rebase is required because of:

1 out of 22 hunks FAILED -- saving rejects to file gcc/cp/parser.cc.rej
1 out of 4 hunks FAILED -- saving rejects to file gcc/cp/pt.cc.rej

but those patch-apply fails look trivial to fix.


And during build, I see:
gcc/cp/decl2.cc:643:20: error: ‘build_non_dependent_expr’ was not declared in 
this scope; did you mean ‘fold_non_dependent_expr’?

For details, see the two commits:
cd0e05b7ac3 c++: remove NON_DEPENDENT_EXPR, part 2
dad311874ac c++: remove NON_DEPENDENT_EXPR, part 1

* * *

When commenting those, even more build issues show up:

../../repos/gcc/gcc/cp/pt.cc:20493:20: error: ‘tsubst_copy’ was not declared in 
this scope; did you mean ‘tsubst_scope’?
20493 | tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, 
in_decl);
  |^~~
  |tsubst_scope
In file included from ../../repos/gcc/gcc/cp/pt.cc:31:
../../repos/gcc/gcc/cp/pt.cc: In function ‘bool 
value_dependent_expression_p(tree)’:
../../repos/gcc/gcc/cp/pt.cc:28009:41: error: ‘t’ was not declared in this 
scope; did you mean ‘tm’?
28009 | tree op0 = RECUR (TREE_OPERAND (t, 0));
  | ^
../../repos/gcc/gcc/system.h:1178:61: note: in definition of macro ‘CONST_CAST2’
 1178 | #define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast (X))
  | ^
../../repos/gcc/gcc/tree.h:1285:31: note: in expansion of macro 
‘TREE_OPERAND_CHECK’
 1285 | #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
  |   ^~
../../repos/gcc/gcc/cp/pt.cc:28009:27: note: in expansion of macro 
‘TREE_OPERAND’
28009 | tree op0 = RECUR (TREE_OPERAND (t, 0));
  |   ^~~~
../../repos/gcc/gcc/cp/pt.cc:28009:20: error: ‘RECUR’ was not declared in this 
scope
28009 | tree op0 = RECUR (TREE_OPERAND (t, 0));
  |^
../../repos/gcc/gcc/cp/pt.cc:28012:11: error: ‘RETURN’ was not declared in this 
scope
28012 |   RETURN (error_mark_node);
  |   ^~

* * *

BTW: There is OpenMP specification Issue 2618 which is about code like "map(*p = 
10)" with the intent to disallow it.
That's in line with the current code which prints a 'sorry' for those.

* * *

libgomp.texi contains:

@item C/C++'s lvalue expressions in @code{to}, @code{from}
  and @code{map} clauses @tab N @tab

I think this can be set to 'P' + 'Only C++'; I think except for questionable 
code like '*p = 10'
the support is complete, isn't it? If no, 'Initial support for C++, only' could 
be a comment.

Alternatively, we can fold it into the next patch (which adds C support).

* * *


2023-09-05  Julian Brown

gcc/c-family/
  * c-common.h (c_omp_address_inspector): Remove static from get_origin
  and maybe_unconvert_ref methods.
  * c-omp.cc (c_omp_split_clauses): Support OMP_ARRAY_SECTION.
  (c_omp_address_inspector::map_supported_p): Handle OMP_ARRAY_SECTION.
  (c_omp_address_inspector::get_origin): Avoid dereferencing possibly
  NULL type when processing template decls.
  (c_omp_address_inspector::maybe_unconvert_ref): Likewise.

gcc/cp/
  * constexpr.cc (potential_consant_expression_1): Handle
  OMP_ARRAY_SECTION.
  * cp-tree.h (grok_omp_array_section, build_omp_array_section): Add
  prototypes.
  * decl2.cc (grok_omp_array_section): New function.
  * error.cc (dump_expr): Handle OMP_ARRAY_SECTION.
  * parser.cc (cp_parser_new): Initialize parser->omp_array_section_p.
  (cp_parser_statement_expr): Disallow array sections.
  (cp_parser_postfix_open_square_expression): Support OMP_ARRAY_SECTION
  parsing.
  (cp_parser_parenthesized_expression_list, cp_parser_lambda_expression,
  cp_parser_braced_list): Disallow array sections.
  (cp_parser_omp_var_list_no_open): Remove ALLOW_DEREF parameter, add
  MAP_LVALUE in its place.  Support generalised lvalue parsing for
  OpenMP map, to and from clauses.  Use OMP_ARRAY_SECTION
  code instead of TREE_LIST to represent OpenMP array sections.
  (cp_parser_omp_var_list): Remove ALLOW_DEREF parameter, add 

Re: [PATCH 1/5] OpenMP, NVPTX: memcpy[23]D bias correction

2023-12-19 Thread Tobias Burnus

Hi Julian & Thomas,

the patch LGTM - and seemingly also Thomas is somewhat fine with it -
and it includes the stand-alone testcase.

* * *

I guess, you don't know the answer to Thomas question, i.e. whether
that's a bug in CUDA or in our use of the CUDA API?

CUDA's spec itself,
https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__MEM.html has
for cuMemcpy2D

‎  void* Start = (void*)((char*)srcHost+srcY*srcPitch + srcXInBytes);

and for cuMemcpy3D

‎  void* Start = (void*)((char*)srcHost+(srcZ*srcHeight+srcY)*srcPitch + 
srcXInBytes);

Thus, I assume we use it "properly", except that the CUDA writers
probably assumed that one allocates a big chunk of memory and work with
that memory and not just maps a subset.

This might or might not be stated in the manual in the following:
"Memory regions spanning over allocations that are both registered and
not registered with CUDA are not supported and will return
CUDA_ERROR_INVALID_VALUE." – where the question is whether everything
until 'start' really counts as "spanning".

Tobias


On 02.10.23 16:53, Julian Brown wrote:

On Wed, 27 Sep 2023 00:57:58 +0200
Thomas Schwinge  wrote:


On 2023-09-06T02:34:30-0700, Julian Brown 
wrote:

This patch works around behaviour of the 2D and 3D memcpy
operations in the CUDA driver runtime.  Particularly in Fortran,
the "base pointer" of an array (used for either source or
destination of a host/device copy) may lie outside of data that is
actually stored on the device.  The fix is to make sure that we use
the first element of data to be transferred instead, and adjust
parameters accordingly.

Do you (a) have a stand-alone test case for this (that is, not
depending on your other pending patches, so that this could go in
directly -- together with the before-FAIL test case).

Thanks for the reply! Here's a version with a stand-alone test case.


Do you (b)
know if is this a bug in our use of the CUDA Driver API or rather in
CUDA itself?  If the latter, have you reported this to Nvidia?

I don't think the CUDA behaviour is *wrong*, as such -- at least to the
C/C++ way of thinking (or indeed a graphics-oriented way of thinking),
one would normally think of an array as having a zero-based origin, and
these 2D/3D memory copies would be intended as a way of updating just a
part of an array (or texture) that has full duplicate copies on both
the host and device.  Our use-case just happens to be a bit different,
both because Fortran (internally) represents an array by a zero-based
origin but may use 1-based (or whatever-based) indices, and because we
support partial mappings of host arrays on the device in all three
supported languages -- which amounts to much the same thing, actually.

That said, it *could* be fixed in CUDA, though probably not in all the
versions currently deployed out there in the world.  So I guess we'd
still need a patch like this anyway.

Julian

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH v7 5/5] OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

2023-12-19 Thread Tobias Burnus

Hi Julian,

On 16.12.23 14:25, Julian Brown wrote:

 OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

 This patch has been separated out from the C++ "declare mapper"
 support patch.  It contains just the gimplify.cc rearrangement
 work, mostly moving gimplification from gimplify_scan_omp_clauses
 to gimplify_adjust_omp_clauses for map clauses.

 The motivation for doing this was that we don't know if we need to
 instantiate mappers implicitly until the body of an offload region has
 been scanned, i.e. in gimplify_adjust_omp_clauses, but we also need the
 un-gimplified form of clauses to sort by base-pointer dependencies after
 mapper instantiation has taken place.

 The patch also reimplements the "present" clause sorting code to avoid
 another sorting pass on mapping nodes.

 This version of the patch is based on the version posted for og13, and
 additionally incorporates a follow-on fix for DECL_VALUE_EXPR handling
 in gimplify_adjust_omp_clauses:

 "OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc"
 https://gcc.gnu.org/pipermail/gcc-patches/2023-June/63.html

 Parts of:
 "OpenMP: OpenMP 5.2 semantics for pointers with unmapped target"
 https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623351.html


I find the patch hard to digest - and I wouldn't be surprised if I
missed something.

However, I think the patch is OK - except for a few minor observations:


 2023-12-16  Julian Brown

 gcc/
 * gimplify.cc (omp_segregate_mapping_groups): Handle "present" 
groups.
 (gimplify_scan_omp_clauses): Use mapping group functionality to
 iterate through mapping nodes.  Remove most gimplification of
 OMP_CLAUSE_MAP nodes from here, but still populate ctx->variables
 splay tree.
 (gimplify_adjust_omp_clauses): Move most gimplification of
 OMP_CLAUSE_MAP nodes here.

 gcc/testsuite/
 * gfortran.dg/gomp/map-12.f90: Adjust scan output.

 libgomp/
 * testsuite/libgomp.fortran/target-enter-data-6.f90: Remove XFAIL.



diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index a6bdceab45d..fa6ddd546f8 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -10107,6 +10114,20 @@ omp_segregate_mapping_groups (omp_mapping_group 
*inlist)
ard_tail = >next;
break;

+ case GOMP_MAP_PRESENT_ALLOC:
+   *pa_tail = w;
+   w->next = NULL;
+   pa_tail = >next;
+   break;
+
+ case GOMP_MAP_PRESENT_FROM:
+ case GOMP_MAP_PRESENT_TO:
+ case GOMP_MAP_PRESENT_TOFROM:
+   *ptf_tail = w;
+   w->next = NULL;
+   ptf_tail = >next;
+   break;
+


First, I note that GOMP_MAP_PRESENT_ALLOC and
GOMP_MAP_PRESENT_{FROM,TO,TOFROM} are semantically identical: If the
variable is not present, error termination will happen - otherwise, if
present, no data movement will happen. Hence, they will be changed to
GOMP_MAP_FORCE_PRESENT in gimplify_adjust_omp_clauses.

That's also the reason that the old code handled all of them identical.

However, besides a plain 'present', there is also 'always' + 'present'.
Those are different as after a normal 'present' check (abort if not
present), the data copying will happen: GOMP_MAP_ALWAYS_PRESENT_TO,
GOMP_MAP_ALWAYS_PRESENT_FROM, GOMP_MAP_ALWAYS_PRESENT_TOFROM.

(Note that: always + present + alloc = GOMP_MAP_PRESENT_ALLOC (w/o
'always') as already done in the FE.)

Thus, all 'case' from your patch should go to a single group (possibly
adding a comment about it). The question is what to do with the
'present,always' case. I think leaving them under 'default:' is fine,
but I might have missed something.


  default:
*tf_tail = w;
w->next = NULL;
@@ -10118,8 +10139,10 @@ omp_segregate_mapping_groups (omp_mapping_group 
*inlist)

* * *

@@ -11922,119 +11945,30 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq 
*pre_p,
  break;
}

-  if (code == OMP_TARGET
-  || code == OMP_TARGET_DATA
-  || code == OMP_TARGET_ENTER_DATA
-  || code == OMP_TARGET_EXIT_DATA)
-{
-  vec *groups;
-  groups = omp_gather_mapping_groups (list_p);
-  if (groups)
- {
-   hash_map *grpmap;
-   grpmap = omp_index_mapping_groups (groups);
+  vec *groups = omp_gather_mapping_groups (list_p);
+  hash_map *grpmap = NULL;
+  unsigned grpnum = 0;
+  tree *grp_start_p = NULL, grp_end = NULL_TREE;


...


-  else if (region_type & ORT_ACC)
-{

I wonder whether you should not better call 'omp_gather_mapping_groups'
only for the 'code == OMP_TARGET...' and for ORT_ACC (or some subset of
OACC *), given that this function is also called
bygimplify_omp_parallel, gimplify_omp_task, gimplify_omp_for, ...

This avoids some memory allocation and list_p walking, i.e. it is not
too bad - but also not really needed for task, parallel, for, ...


@@ -14008,26 +13926,73 @@ 

Re: [PATCH v7 4/5] OpenMP/OpenACC: Unordered/non-constant component offset runtime diagnostic

2023-12-14 Thread Tobias Burnus

On 19.08.23 00:47, Julian Brown wrote:

This patch adds support for non-constant component offsets in "map"
clauses for OpenMP (and the equivalants for OpenACC), which are not able
to be sorted into order at compile time.  Normally struct accesses in
such clauses are gathered together and sorted into increasing address
order after a "GOMP_MAP_STRUCT" node: if we have variable indices,
that is no longer possible.

This version of the patch scales back the previously-posted version to
merely add a diagnostic for incorrect usage of component accesses with
variably-indexed arrays of structs: the only permitted variant is where
we have multiple indices that are the same, but we could not prove so
at compile time.  Rather than silently producing the wrong result for
cases where the indices are in fact different, we error out (e.g.,
"map(dtarr(i)%arrptr, dtarr(j)%arrptr(4:8))", for different i/j).

For now, multiple *constant* array indices are still supported (see
map-arrayofstruct-1.c).  That could perhaps be addressed with a follow-up
patch, if necessary.

This version of the patch renumbers the GOMP_MAP_STRUCT_UNORD kind to
avoid clashing with the OpenACC "non-contiguous" dynamic array support
(though that is not yet applied to mainline).


LGTM with:

- inclusion of your follow-up fix for shared-memory systems (see email
of August 21)

- adding a comment to map-arrayofstruct-1.c indicating that this usage
is an extension, violating a restriction (be a bit more explicit that
just that)

See https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603126.html
for a quote of the specification or (same wording, newer spec) in TR12
under "Restrictions to the map clause are as follows:" in "6.8.3 map
Clause" [218+219:36-37+1-3]

Thanks,

Tobias


2023-08-18  Julian Brown  

gcc/
  * gimplify.cc (extract_base_bit_offset): Add VARIABLE_OFFSET parameter.
  (omp_get_attachment, omp_group_last, omp_group_base,
  omp_directive_maps_explicitly): Add GOMP_MAP_STRUCT_UNORD support.
  (omp_accumulate_sibling_list): Update calls to extract_base_bit_offset.
  Support GOMP_MAP_STRUCT_UNORD.
  (omp_build_struct_sibling_lists, gimplify_scan_omp_clauses,
  gimplify_adjust_omp_clauses, gimplify_omp_target_update): Add
  GOMP_MAP_STRUCT_UNORD support.
  * omp-low.cc (lower_omp_target): Add GOMP_MAP_STRUCT_UNORD support.
  * tree-pretty-print.cc (dump_omp_clause): Likewise.

include/
  * gomp-constants.h (gomp_map_kind): Add GOMP_MAP_STRUCT_UNORD.

libgomp/
  * oacc-mem.c (find_group_last, goacc_enter_data_internal,
  goacc_exit_data_internal, GOACC_enter_exit_data): Add
  GOMP_MAP_STRUCT_UNORD support.
  * target.c (gomp_map_vars_internal): Add GOMP_MAP_STRUCT_UNORD support.
  Detect incorrect use of variable indexing of arrays of structs.
  (GOMP_target_enter_exit_data, gomp_target_task_fn): Add
  GOMP_MAP_STRUCT_UNORD support.
  * testsuite/libgomp.c-c++-common/map-arrayofstruct-1.c: New test.
  * testsuite/libgomp.c-c++-common/map-arrayofstruct-2.c: New test.
  * testsuite/libgomp.c-c++-common/map-arrayofstruct-3.c: New test.
  * testsuite/libgomp.fortran/map-subarray-5.f90: New test.
---
  gcc/gimplify.cc   | 110 ++
  gcc/omp-low.cc|   1 +
  gcc/tree-pretty-print.cc  |   3 +
  include/gomp-constants.h  |   6 +
  libgomp/oacc-mem.c|   6 +-
  libgomp/target.c  |  60 +-
  .../map-arrayofstruct-1.c |  38 ++
  .../map-arrayofstruct-2.c |  58 +
  .../map-arrayofstruct-3.c |  68 +++
  .../libgomp.fortran/map-subarray-5.f90|  54 +
  10 files changed, 377 insertions(+), 27 deletions(-)
  create mode 100644 
libgomp/testsuite/libgomp.c-c++-common/map-arrayofstruct-1.c
  create mode 100644 
libgomp/testsuite/libgomp.c-c++-common/map-arrayofstruct-2.c
  create mode 100644 
libgomp/testsuite/libgomp.c-c++-common/map-arrayofstruct-3.c
  create mode 100644 libgomp/testsuite/libgomp.fortran/map-subarray-5.f90

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index fad4308a0eb4..e682583054b0 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -8965,7 +8965,8 @@ build_omp_struct_comp_nodes (enum tree_code code, tree 
grp_start, tree grp_end,

  static tree
  extract_base_bit_offset (tree base, poly_int64 *bitposp,
-  poly_offset_int *poffsetp)
+  poly_offset_int *poffsetp,
+  bool *variable_offset)
  {
tree offset;
poly_int64 bitsize, bitpos;
@@ -8983,10 +8984,13 @@ extract_base_bit_offset (tree base, poly_int64 *bitposp,
if (offset && poly_int_tree_p (offset))
  {
poffset = wi::to_poly_offset (offset);
-  offset = NULL_TREE;
+  *variable_offset = false;
  }
else
-poffset = 0;
+{
+  

RE: [PATCH v7] libgfortran: Replace mutex with rwlock

2023-12-14 Thread Tobias Burnus


 
 
  
   Hi,
   
   
   
Thomas Schwinge wrote:

   
 

   
On 2023-12-14T02:28:22+, "Zhu, Lipeng"  wrote:



 On 2023/12/14 4:52, Thomas Schwinge wrote:
 >> I've just filed > Would you be able to look into that?

   
 



 Sure, I will look into that.
 



 BTW, I didn’t have the PowerPC in hands, do you mind granting the access of your
 

 test environment to me to help reproduce the issue?
 

   
That's unfortunately not possible:

   
  
   How about https://gcc.gnu.org/wiki/CompileFarm I think there is a PowerPC system available.
   
  
    
   
  
   Tobias
   
  
    
   
  
    
  
 



[Patch] OpenMP: Minor '!$omp allocators' cleanup - and still: Re: [patch] OpenMP/Fortran: Implement omp allocators/allocate for ptr/allocatables

2023-12-11 Thread Tobias Burnus

Hi Thomas & Jakub,

I included a minor cleanup patch - but the rest is really a bunch of RFC.

I intent to commit that patch as obvious, unless there are further comments.

On 09.12.23 16:14, Jakub Jelinek wrote:


There were 3 reasons to add GOMP_alloc (and 1 for GOMP_free):
1) when it was added, omp_aligned_alloc was still not exported from the
library because we thought we shouldn't expose 5.1 features until we
have 5.0 implemented (then changed mind)
2) unline omp_aligned_alloc, GOMP_alloc issues fatal error on allocation
failure
3) the omp_* functions have omp_allocator_handle_t arguments, which is hard
to provide for builtins (I think this is the only reason for GOMP_free
addition, maybe together with wanting those to be paired)


Is this a real issue? GOMP_{alloc,free} take uintptr_t as allocator
while omp_* take omp_allocator_handle_t.

But that contains a __omp_memspace_handle_t_max__ = __UINTPTR_MAX__ and
>= C++ 11 ': __UINTPTR_TYPE__' for C/C++ and omp_allocator_handle_kind
= c_intptr_t in Fortran (→ integer(c_intptr_t) = signed variant of
uintptr_t).

In Fortran, there is an explicit check that the allocator has that kind,
which is a check whether it is kind=4 or kind=8, respectively, depending
what kind matches intptr_t. Thus, for Fortran, there is already a mismatch.

Thus, it seems to be at most a C/C++ issue.


Now, 1) is a non-issue anymore, I don't know what Fortran wants for
allocation failures, if it is better to have diagnostics on the libgomp side
or if wants to emit it inline.


I think that's not quite clear, while for Fortran itself and for
OpenMP's omp_alloc routine, the behavior is well defined, it is not for
'!$omp allocators'.

However, I think using omp_alloc is more Fortranish.

I think it would be a tad cleaner to change it – but the question is how
to do it best:

Even when ignoring the uintptr_t vs. omp_allocator_handle_t issue, the
question is still how to handle it best.

Create another builtin - to make it possible to add it to
gimple-ssa-warn-access.cc / tree-ssa-ccp.cc / tree-ssa-dce.cc?

Or the alternative: Be more un-Fortranish and keep the current
GOMP_alloc handling?

Thoughts?


And yes, 3) would be an argument to add
GOMP_realloc.


I am happy to add GOMP_realloc – passing 0 for old/new allocator in case
of Fortran - if it really makes sense. Otherwise, I'd keep it as is.

I think the next user would be the (pseudo-)USM patches, i.e. replacing
all (re,c,m)alloc/free by calls to omp_(re,c,)alloc/omp_free + special
allocator when -foffload-memory={none,pinned,unified} (well, not when
=none). Those are a bit fragile but permit using pinned/USM on less
capable offload devices. (Feature exists also with other compilers, i.e.
the users seem to be used to the limitations of this feature.)

Thus, one option would be to wait until that feature is ready.

What would be the NULL behavior? As omp_alloc or as GOMP_alloc? I assume
as omp_alloc would be fine?

* * *

On 09.12.23 12:19, Thomas Schwinge wrote:

Why not define 'GOMP_add_alloc', 'GOMP_is_alloc' via 'gcc/omp-builtins.def'?


We could - but does it make sense to have it for a single caller?


Should this either be 'BUILT_IN_OMP_REALLOC' ('OMP' instead of 'GOMP'),
or otherwise a 'GOMP_realloc' be added to 'libgomp/allocator.c

Cf. also above. but I am fine with a name change to OMP_ as well/in addition.


'GOMP_add_alloc', 'GOMP_is_alloc' should get prototyped in
'libgomp/libgomp_g.h'.


I concur + added.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Minor '!$omp allocators' cleanup

gcc/fortran/ChangeLog:

	* trans-openmp.cc (gfc_omp_call_add_alloc,
	gfc_omp_call_is_alloc): Set 'fn spec'.

libgomp/ChangeLog:

	* libgomp_g.h (GOMP_add_alloc, GOMP_is_alloc): Add.

 gcc/fortran/trans-openmp.cc | 8 ++--
 libgomp/libgomp_g.h | 3 +++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 9e166c94f8e..95184920cf7 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -8361,8 +8361,10 @@ gfc_omp_call_add_alloc (tree ptr)
   if (fn == NULL_TREE)
 {
   fn = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+  tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
+  att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
+  fn = build_type_attribute_variant (fn, att);
   fn = build_fn_decl ("GOMP_add_alloc", fn);
-/* FIXME: attributes.  */
 }
   return build_call_expr_loc (input_location, fn, 1, ptr);
 }
@@ -8380,7 +8382,9 @@ gfc_omp_call_is_alloc (tree ptr)
   fn = build_function_type_list (boolean_type_node, ptr_type_node,
  NULL_TREE);
   fn = build_fn_decl ("GOMP_is_alloc", 

Re: [PATCH v7 3/5] OpenMP: Pointers and member mappings

2023-12-11 Thread Tobias Burnus

Hi Julian,

On 07.12.23 18:24, Julian Brown wrote:

On Wed, 6 Dec 2023 12:36:34 +0100
Tobias Burnus  wrote:


LGTM, except for:

* The 'target exit data' handling - comments below - looks a bit
fishy/inconsistent.

...

Thus, I wonder whether that shouldn't be instead
OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE
? GOMP_MAP_DELETE : GOMP_MAP_RELEASE;

I've fixed that as you suggest.  Actually I've made OpenACC use the new
node layout as well, since (a) it works and (b) it was weirdly
inconsistent before.  That is, exit data directives will no longer use
e.g.:

   GOMP_MAP_FROM
   GOMP_MAP_TO_PSET
   GOMP_MAP_ATTACH_DETACH

but instead,

   GOMP_MAP_FROM
   GOMP_MAP_RELEASE (with OMP_CLAUSE_RELEASE_DESCRIPTOR set)
   GOMP_MAP_ATTACH_DETACH

actually the current state is that GOMP_MAP_TO_PSET will be used for
the descriptor on an "exit data" directive if you refer to the whole
array, but GOMP_MAP_RELEASE (etc.) will be used if you refer to an array
section (without the flag newly added in this patch, of course). I
don't think there's any reason to maintain that inconsistency.

...

I've re-tested this version. Does it look better now?


Yes, LGTM as well.

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH v7 3/5] OpenMP: Pointers and member mappings

2023-12-06 Thread Tobias Burnus

Hi Julian,

LGTM, except for:

* The 'target exit data' handling - comments below - looks a bit
fishy/inconsistent.

I intent to have a closer look with more code context, but maybe you
should have a look at it as well.

BTW: Fortran deep-mapping is not yet on mainline. Are you aware of
changes or in particular testcases on OG13 related to your patch series
that should be included when upstreaming that auto-mapping of
allocatable components patch?

* * *

On 19.08.23 00:47, Julian Brown wrote:

This patch changes the mapping node arrangement used for array components
of derived types in order to accommodate for changes made in the previous
patch, particularly the use of "GOMP_MAP_ATTACH_DETACH" for pointer-typed
derived-type members instead of "GOMP_MAP_ALWAYS_POINTER".

We change the mapping nodes used for a derived-type mapping like this:

   type T
   integer, pointer, dimension(:) :: arrptr
   end type T

   type(T) :: tvar
   [...]
   !$omp target map(tofrom: tvar%arrptr)

So that the nodes used look like this:

   1) map(to: tvar%arrptr)   -->
   GOMP_MAP_TO [implicit]  *tvar%arrptr%data  (the array data)
   GOMP_MAP_TO_PSETtvar%arrptr(the descriptor)
   GOMP_MAP_ATTACH_DETACH  tvar%arrptr%data

   2) map(tofrom: tvar%arrptr(3:8)   -->
   GOMP_MAP_TOFROM *tvar%arrptr%data(3)  (size 8-3+1, etc.)


[Clarification for the patch readers - not to the patch writer]

At least to me the wording or implications of (1) were not fully clear to
me. However, it is intended that the implicit mapping ensures that the
pointer is actually mapped.

Fortunately, that's indeed the case :-)
as testing and also the new testcase 
libgomp/testsuite/libgomp.fortran/map-subarray-4.f90  shows.

The related part comes from OpenMP 5.1 [349:9-12] or slightly refined
later, here the TR12 wording:

If a list item in a map clause is an associated pointer that is not 
attach-ineligible and the pointer is
not the base pointer of another list item in a map clause on the same 
construct, then it is treated as if
its pointer target is implicitly mapped in the same clause. For the purposes of 
the map clause, the
mapped pointer target is treated as if its base pointer is the associated 
pointer."  [213:18-21]

* * *


[...]
In the middle end, we process mappings using the struct sibling-list
handling machinery by moving the "GOMP_MAP_TO_PSET" node from the middle
of the group of three mapping nodes to the proper sorted position after
the GOMP_MAP_STRUCT mapping:

   GOMP_MAP_STRUCT   tvar (len: 1)
   GOMP_MAP_TO_PSET  tvar%arr (size: 64, etc.)  <--. moved here
   [...]   |
   GOMP_MAP_TOFROM *tvar%arrptr%data(3) ___|
   GOMP_MAP_ATTACH_DETACH  tvar%arrptr%data

In another case, if we have an array of derived-type values "dtarr",
and mappings like:

   i = 1
   j = 1
   map(to: dtarr(i)%arrptr) map(tofrom: dtarr(j)%arrptr(3:8))

We still map the same way, but this time we cannot prove that the base
expressions "dtarr(i) and "dtarr(j)" are the same in the front-end.
So we keep both mappings, but we move the "[implicit]" mapping of the
full-array reference to the end of the clause list in gimplify.cc (by
adjusting the topological sorting algorithm):

   GOMP_MAP_STRUCT dtvar  (len: 2)
   GOMP_MAP_TO_PSETdtvar(i)%arrptr
   GOMP_MAP_TO_PSETdtvar(j)%arrptr
   [...]
   GOMP_MAP_TOFROM *dtvar(j)%arrptr%data(3)  (size: 8-3+1)
   GOMP_MAP_ATTACH_DETACH  dtvar(j)%arrptr%data
   GOMP_MAP_TO [implicit]  *dtvar(i)%arrptr%data(1)  (size: whole array)
   GOMP_MAP_ATTACH_DETACH  dtvar(i)%arrptr%data

Always moving "[implicit]" full-array mappings after array-section
mappings (without that bit set) means that we'll avoid copying the whole
array unnecessarily -- even in cases where we can't prove that the arrays
are the same.

The patch also fixes some bugs with "enter data" and "exit data"
directives with this new mapping arrangement.  Also now if you have
mappings like this:

   #pragma omp target enter data map(to: dv, dv%arr(1:20))

The whole of the derived-type variable "dv" is mapped, so the
GOMP_MAP_TO_PSET for the array-section mapping can be dropped:

   GOMP_MAP_TOdv

   GOMP_MAP_TO*dv%arr%data
   GOMP_MAP_TO_PSET   dv%arr <-- deleted (array section mapping)
   GOMP_MAP_ATTACH_DETACH dv%arr%data

To accommodate for recent changes to mapping nodes made by
Tobias, this version of the patch avoids using GOMP_MAP_TO_PSET
for "exit data" directives, in favour of using the "correct"
GOMP_MAP_RELEASE/GOMP_MAP_DELETE kinds during early expansion.  A new
flag is introduced so the middle-end knows when the latter two kinds
are being used specifically for an array descriptor.

This version of the patch is based on the version posted for the og13
branch:

https://gcc.gnu.org/pipermail/gcc-patches/2023-June/62.html

[...]


+  if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE
+   || OMP_CLAUSE_MAP_KIND (node) == 

Re: [PATCH] libgfortran: Fix -Wincompatible-pointer-types errors

2023-12-05 Thread Tobias Burnus

Hi all,

the patch submission looks confusing as the context is a bit unclear
(aarch64 having two integer types?) and the slightly unmotivated 'long'
change (as explained in later emails: used as trick to find all
locations that should be changed and not being part of actually proposed
patch).

However, once this has been disentangled, the patch LGTM, assuming and
being positive that no aarch64 maintainer sees a problem.

Tobias

On 05.12.23 11:33, Jakub Jelinek wrote:

On Tue, Dec 05, 2023 at 10:46:02AM +0100, Florian Weimer wrote:

Presumably the fixes will look like this?

diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index db3330060ce..4fcc77dbf83 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -2987,13 +2987,13 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info *nl, 
index_type offset,
 /* If this object has a User Defined procedure, call it.  */
 if (nl->dtio_sub != NULL)
   {
-int unit = dtp->u.p.current_unit->unit_number;
+GFC_INTEGER_4 unit = dtp->u.p.current_unit->unit_number;
 char iotype[] = "NAMELIST";
 gfc_charlen_type iotype_len = 8;
 char tmp_iomsg[IOMSG_LEN] = "";
 char *child_iomsg;
 gfc_charlen_type child_iomsg_len;
-int noiostat;
+GFC_INTEGER_4 noiostat;
 int *child_iostat = NULL;
 gfc_full_array_i4 vlist;
 formatted_dtio dtio_ptr = (formatted_dtio)nl->dtio_sub;

That seems insufficient.

The following patch makes libgfortran build on i686-linux after hacking up
--- kinds.h.xx2023-12-05 00:23:00.133365064 +0100
+++ kinds.h   2023-12-05 11:19:24.409679808 +0100
@@ -10,8 +10,8 @@ typedef GFC_INTEGER_2 GFC_LOGICAL_2;
  #define HAVE_GFC_LOGICAL_2
  #define HAVE_GFC_INTEGER_2

-typedef int32_t GFC_INTEGER_4;
-typedef uint32_t GFC_UINTEGER_4;
+typedef long GFC_INTEGER_4;
+typedef unsigned long GFC_UINTEGER_4;
  typedef GFC_INTEGER_4 GFC_LOGICAL_4;
  #define HAVE_GFC_LOGICAL_4
  #define HAVE_GFC_INTEGER_4
in the build dir to emulate what newlib aarch64 is doing:

2023-12-05  Florian Weimer  
  Jakub Jelinek  

  * io/list_read.c (list_formatted_read_scalar) :
  Change types of unit and noiostat to GFC_INTEGER_4 from int, change
  type of child_iostat from to GFC_INTEGER_4 * from int *, formatting
  fixes.
  (nml_read_obj): Likewise.
  * io/write.c (list_formatted_write_scalar) : Likewise.
  (nml_write_obj): Likewise.
  * io/transfer.c (unformatted_read, unformatted_write): Likewise.

--- libgfortran/io/list_read.c.jj 2023-05-09 00:07:26.161168737 +0200
+++ libgfortran/io/list_read.c2023-12-05 11:25:31.837426653 +0100
@@ -2189,14 +2189,14 @@ list_formatted_read_scalar (st_parameter
break;
  case BT_CLASS:
{
-   int unit = dtp->u.p.current_unit->unit_number;
+   GFC_INTEGER_4 unit = dtp->u.p.current_unit->unit_number;
char iotype[] = "LISTDIRECTED";
gfc_charlen_type iotype_len = 12;
char tmp_iomsg[IOMSG_LEN] = "";
char *child_iomsg;
gfc_charlen_type child_iomsg_len;
-   int noiostat;
-   int *child_iostat = NULL;
+   GFC_INTEGER_4 noiostat;
+   GFC_INTEGER_4 *child_iostat = NULL;
gfc_full_array_i4 vlist;

GFC_DESCRIPTOR_DATA() = NULL;
@@ -2204,8 +2204,8 @@ list_formatted_read_scalar (st_parameter

/* Set iostat, intent(out).  */
noiostat = 0;
-   child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
-   dtp->common.iostat : 
+   child_iostat = ((dtp->common.flags & IOPARM_HAS_IOSTAT)
+   ? dtp->common.iostat : );

/* Set iomsge, intent(inout).  */
if (dtp->common.flags & IOPARM_HAS_IOMSG)
@@ -2987,14 +2987,14 @@ nml_read_obj (st_parameter_dt *dtp, name
  /* If this object has a User Defined procedure, call it.  */
  if (nl->dtio_sub != NULL)
{
- int unit = dtp->u.p.current_unit->unit_number;
+ GFC_INTEGER_4 unit = dtp->u.p.current_unit->unit_number;
  char iotype[] = "NAMELIST";
  gfc_charlen_type iotype_len = 8;
  char tmp_iomsg[IOMSG_LEN] = "";
  char *child_iomsg;
  gfc_charlen_type child_iomsg_len;
- int noiostat;
- int *child_iostat = NULL;
+ GFC_INTEGER_4 noiostat;
+ GFC_INTEGER_4 *child_iostat = NULL;
  gfc_full_array_i4 vlist;
  formatted_dtio dtio_ptr = (formatted_dtio)nl->dtio_sub;

@@ -3006,8 +3006,8 @@ nml_read_obj (st_parameter_dt *dtp, name

  /* Set iostat, intent(out).  */
  noiostat = 0;
- child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
- dtp->common.iostat : 
+ child_iostat = ((dtp->common.flags & IOPARM_HAS_IOSTAT)
+ ? 

Re: [PATCH v7 2/5] OpenMP/OpenACC: Rework clause expansion and nested struct handling

2023-11-29 Thread Tobias Burnus

Hi Julian,

On 29.11.23 12:43, Julian Brown wrote:

Here is a patch incorporating your initial review comments
(hopefully!).


Thanks.

The patch LGTM - with the two remarks below addressed.

(i.e. fixing one testcase and filing two PRs (or common PR) about the features
missing and exposed by the two test cases, referencing also to those testcases
- and for the lvalues mentioning the OpenMP spec issue number.)

* * *

BTW: The 1/5 has been several times approved and is just reindenting - and
is obviously still OK.


(Review wise, 3/5, 4/5 and 5/5 still has to be done.

I think the patch can go in before - given the huge improvements, even though
it regresses for a few cases (xfail added for 2 Fortran testcases). 3/5 
un-xfails
one and a half of the textcases, 5/5 un-xfails the remaining half and all of 
{3,4,5}/5
contain very useful improvements besides this. - But maybe waiting for at least 
3/5
makes sense.

In either case, I try to review the remaining patches soon.)

* * *

Question regarding the following:
(a) The dg-xfail-run-if looks bogus as this an OpenMP test and not an OpenACC 
test
(b) If there is shared memory, using 'omp target' should be fine.

Namely, given that:


--- /dev/null +++ b/libgomp/testsuite/libgomp.c++/target-49.C @@ -0,0
+1,37 @@ +#include  +#include  + +struct s { + int
()[10]; + s(int ()[10]) : a(a0) {} +}; + +int +main (int argc,
char *argv[]) +{ + int la[10]; + s v_real(la); + s *v = _real; + +
memset (la, 0, sizeof la); + + #pragma omp target enter data map(to:
v) + + /* Copying the whole v[0] here DOES NOT WORK yet because the
reference 'a' is + not copied "as if" it was mapped explicitly as a
member. FIXME. */ + #pragma omp target enter data map(to: v[0]) + +
//#pragma omp target + { + v->a[5]++; + } + + #pragma omp target exit
data map(release: v[0]) + #pragma omp target exit data map(from: v) +
+ assert (v->a[5] == 1); + + return 0; +} + +// { dg-xfail-run-if
"TODO" { *-*-* } { "-DACC_MEM_SHARED=0" } }

Shouldn't the XFAIL not be based on '{ target offload_device_nonshared_as }'
and the 'omp target' be uncommented?

And I wonder whether we need to file a PR about this issue - I guess it is not
addressed by any of the follow-up issues and might get forgotten unless there 
is PR.


* * *

libgomp/testsuite/libgomp.c++/baseptrs-4.C ... // Needs map clause
"lvalue"-parsing support. //#define REF2ARRAY_DECL_BASE


There is an open OpenMP issue to disallow some lvalues, namely:
OpenMP Issue 2618 ("Clarify behavior of mapping lvalues on target construct")
talks about code like the following

  map(*p = 10)
  map(x = 20)
  map(x ? y[0] : p[1])
  map(f(y))

is valid or not. The sentiment was to require that a 'map' clause list item
must have a base pointer or a base variable.


However, it looks as your examples would be valid in this regard. Can you file
a PR about this one? Referencing both to this testcase and to the OpenMP issue?

(I do note that Clang and GCC reject the lvalue examples from the OpenMP issue
but not your reference examples; those are accepted by clang++-14.)


Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH v2] Fortran: fix reallocation on assignment of polymorphic variables [PR110415]

2023-11-28 Thread Tobias Burnus

Hi Andrew,

On 27.11.23 18:35, Andrew Jenner wrote:

This is the second version of the patch - previous discussion at:
https://gcc.gnu.org/pipermail/gcc-patches/2023-November/636671.html

This patch adds the testcase from PR110415 and fixes the bug.

The problem is that in a couple of places in trans_class_assignment in
trans-expr.cc, we need to get the run-time size of the polymorphic
object from the vtbl, but we are currently getting that vtbl from the
lhs of the assignment rather than the rhs. This gives us the old value
of the size but we need to pass the new size to __builtin_malloc and
__builtin_realloc.

I'm fixing this by adding a parameter to trans_class_vptr_len_assignment
to retrieve the tree corresponding the vptr from the object on the rhs
of the assignment, and then passing this where it is needed. In the case
where trans_class_vptr_len_assignment returns NULL_TREE for the rhs vptr
we use the lhs vptr as before.

To get this to work I also needed to change the implementation of
trans_class_vptr_len_assignment to create a temporary for the assignment
in more circumstances. Currently, the "a = func()" assignment in MAIN__
doesn't hit the "Create a temporary for complication expressions" case
on line 9951 because "DECL_P (rse->expr)" is true - the expression has
already been placed into a temporary. That means we don't hit the "if
(temp_rhs ..." case on line 10038 and go on to get the vptr_expr from
"gfc_lval_expr_from_sym (gfc_find_vtab (>ts))" on line 10057 which
is the vtbl of the static type rather than the dynamic one from the rhs.
So with this fix we create an extra temporary, but that should be
optimised away in the middle-end so there should be no run-time effect.

I'm not sure if this is the best way to fix this (the Fortran front-end
is new territory for me) but I've verified that the testcase passes with
this change, fails without it, and that the change does not introduce
any FAILs when running the gfortran testcases on x86_64-pc-linux-gnu.

After the previous submission, Tobias Burnus found a closely related
problem and contributed testcases and a fix for it, which I have
incorporated into this version of the patch. The problem in this case
is with the __builtin_realloc call that is executed if one polymorphic
variable is replaced by another. The return value of this call was
being ignored rather than used to replace the pointer being reallocated.

Is this OK for mainline, GCC 13 and OG13?


LGTM – Thanks! OK for mainline and after some grace period for GCC 13.

OG13 does not require approval, hence, either cherry pick directly or
wait until it is in GCC 13 and then "git merge" GCC 13 to OG13.

Thanks,

Tobias



gcc/fortran/
 PR fortran/110415
 * trans-expr.cc (trans_class_vptr_len_assignment): Add
 from_vptrp parameter. Populate it. Don't check for DECL_P
 when deciding whether to create temporary.
 (trans_class_pointer_fcn, gfc_trans_pointer_assignment): Add
 NULL argument to trans_class_vptr_len_assignment calls.
 (trans_class_assignment): Get rhs_vptr from
 trans_class_vptr_len_assignment and use it for determining size
 for allocation/reallocation. Use return value from realloc.

gcc/testsuite/
 PR fortran/110415
 * gfortran.dg/pr110415.f90: New test.
 * gfortran.dg/asan/pr110415-2.f90: New test.
 * gfortran.dg/asan/pr110415-3.f90: New test.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[Patch] OpenMP: Support acquires/release in 'omp require atomic_default_mem_order'

2023-11-28 Thread Tobias Burnus

I stumbled over this omission when looking at Sandra's patch. It turned out 
that this is
a new OpenMP 5.2 feature - probably added to simplify/unify the syntax. I guess 
the reason
that release/acquire wasn't added before is that it cannot be universally be 
used - read/write
do only accept one of them.

However, as a compilation unit might only/mostly use read (and update) or write 
(and update),
that can be fine - especially as overriding the default clause is still 
possible.

It is not quite clear to me why, but the current patch also fixes a bug 
regarding the
diagnostic message for gfortran.dg/gomp/requires-5.f90. (I think I could find 
out, but
as it changed to the better...)

Comments, suggestions?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Support acquires/release in 'omp require atomic_default_mem_order'

This is an OpenMP 5.2 feature.

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_omp_requires): Handle acquires/release
	in atomic_default_mem_order clause.
	(c_parser_omp_atomic): Update. 

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_requires): Handle acquires/release
	in atomic_default_mem_order clause.
	(cp_parser_omp_atomic): Update.

gcc/fortran/ChangeLog:

	* gfortran.h (enum gfc_omp_requires_kind): Add
	OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE and OMP_REQ_ATOMIC_MEM_ORDER_RELEASE.
	(gfc_namespace): Add a 7th bit to omp_requires.
	* module.cc (enum ab_attribute): Add AB_OMP_REQ_MEM_ORDER_ACQUIRE
	and AB_OMP_REQ_MEM_ORDER_RELEASE
	(mio_symbol_attribute): Handle it.
	* openmp.cc (gfc_omp_requires_add_clause): Update for acquire/release.
	(gfc_match_omp_requires): Likewise.
	(gfc_match_omp_atomic): Handle them for atomic_default_mem_order.
	* parse.cc: Likewise.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/requires-3.c: Update for now valid code.
	* gfortran.dg/gomp/requires-3.f90: Likewise.
	* gfortran.dg/gomp/requires-2.f90: Update dg-error.
	* gfortran.dg/gomp/requires-5.f90: Likewise.
	* c-c++-common/gomp/requires-5.c: New test.
	* c-c++-common/gomp/requires-6.c: New test.
	* c-c++-common/gomp/requires-7.c: New test.
	* c-c++-common/gomp/requires-8.c: New test.
	* gfortran.dg/gomp/requires-10.f90: New test.
	* gfortran.dg/gomp/requires-11.f90: New test.

 gcc/c/c-parser.cc  | 32 +++-
 gcc/cp/parser.cc   | 32 +++-
 gcc/fortran/gfortran.h | 22 ++-
 gcc/fortran/module.cc  | 19 +
 gcc/fortran/openmp.cc  | 53 +-
 gcc/fortran/parse.cc   |  8 
 gcc/testsuite/c-c++-common/gomp/requires-3.c   |  8 ++--
 gcc/testsuite/c-c++-common/gomp/requires-5.c   | 23 +++
 gcc/testsuite/c-c++-common/gomp/requires-6.c   | 23 +++
 gcc/testsuite/c-c++-common/gomp/requires-7.c   | 11 ++
 gcc/testsuite/c-c++-common/gomp/requires-8.c   | 14 +++
 gcc/testsuite/gfortran.dg/gomp/requires-10.f90 | 36 +
 gcc/testsuite/gfortran.dg/gomp/requires-11.f90 | 31 +++
 gcc/testsuite/gfortran.dg/gomp/requires-2.f90  |  2 +-
 gcc/testsuite/gfortran.dg/gomp/requires-3.f90  |  7 ++--
 gcc/testsuite/gfortran.dg/gomp/requires-5.f90  |  2 +-
 16 files changed, 291 insertions(+), 32 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index df9a07928b5..5700c49 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -20896,6 +20896,28 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
 	case OMP_MEMORY_ORDER_SEQ_CST:
 	  memory_order = OMP_MEMORY_ORDER_SEQ_CST;
 	  break;
+	case OMP_MEMORY_ORDER_ACQUIRE:
+	  if (code == NOP_EXPR)  /* atomic write */
+	{
+	  error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+			 "% clause implicitly provided by a "
+			 "% directive");
+	  memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+	}
+	  else
+	memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+	  break;
+	case OMP_MEMORY_ORDER_RELEASE:
+	  if (code == OMP_ATOMIC_READ)
+	{
+	  error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+			 "% clause implicitly provided by a "
+			 "% directive");
+	  memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+	}
+	  else
+	memory_order = OMP_MEMORY_ORDER_RELEASE;
+	  break;
 	case OMP_MEMORY_ORDER_ACQ_REL:
 	  switch (code)
 	{
@@ -25724,15 +25746,21 @@ c_parser_omp_requires (c_parser *parser)
 		  else if (!strcmp (p, "relaxed"))
 			this_req
 			  = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+		  else if (!strcmp (p, "release"))
+			this_req
+			  = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
 		  else if (!strcmp (p, "acq_rel"))
 			this_req
 			  = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+		  

Re: [patch] OpenMP: Add -Wopenmp and use it

2023-11-27 Thread Tobias Burnus

Hi,

On 27.11.23 11:20, Christophe Lyon wrote:


I think the lack of final '.' in:


Indeed - but you are lagging a bit behind:

https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638128.html

[committed] c-family/c.opt (-Wopenmp): Add missing tailing '.'

Fri Nov 24 18:56:21 GMT 2023

Committed as r14-5835-g6eb1507107dee3

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[patch] OpenMP: Add -Wopenmp and use it

2023-11-24 Thread Tobias Burnus

Following the general trend to add a "[-W...]" to the warning messages
for both better grouping of the warnings and - more importantly - for providing
a means to silence such a warning (or to -Werror= them explicitly), this patch
replaces several '0' by OPT_Wopenmp.

Comments or remarks before I commit it?

Tobias

PS: This does not cover all OpenMP warnings: Besides those '0' that I have 
missed,
there are also some warnings which use a different -W...  - I have not checked
whether their current -W... value or -Wopenmp makes more sense for them.
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Add -Wopenmp and use it

The new warning has two purposes: First, it makes clearer to the
user that it is about OpenMP and, secondly and more importantly,
it permits to use -Wno-openmp.

The newly added -Wopenmp is enabled by default and replaces the
'0' (always warning) in several OpenMP-related warning calls.
For code shared with OpenACC, it only uses OPT_Wopenmp for
'flag_openmp | flag_openmp_simd'.

gcc/c-family/ChangeLog:

	* c.opt (Wopenmp): Add, enable by default.

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_omp_clause_num_threads,
	c_parser_omp_clause_num_tasks, c_parser_omp_clause_grainsize,
	c_parser_omp_clause_priority, c_parser_omp_clause_schedule,
	c_parser_omp_clause_num_teams, c_parser_omp_clause_thread_limit,
	c_parser_omp_clause_dist_schedule, c_parser_omp_scan_loop_body,
	c_parser_omp_assumption_clauses): Add OPT_Wopenmp to warning_at.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_clause_dist_schedule,
	cp_parser_omp_scan_loop_body, cp_parser_omp_assumption_clauses):
	Add OPT_Wopenmp to warning_at.
	* semantics.cc (finish_omp_clauses): Likewise.

gcc/ChangeLog:

	* doc/invoke.texi (-Wopenmp): Add.
	* gimplify.cc (gimplify_omp_for): Add OPT_Wopenmp to warning_at.
	* omp-expand.cc (expand_omp_ordered_sink): Likewise.
	* omp-general.cc (omp_check_context_selector): Likewise.
	* omp-low.cc (scan_omp_for, check_omp_nesting_restrictions,
	lower_omp_ordered_clauses): Likewise.
	* omp-simd-clone.cc (simd_clone_clauses_extract): Likewise.

gcc/fortran/ChangeLog:

	* lang.opt (Wopenmp): Add, enabled by dafault and documented in C.
	* openmp.cc (gfc_match_omp_declare_target, resolve_positive_int_expr,
	resolve_nonnegative_int_expr, resolve_omp_clauses,
	gfc_resolve_omp_do_blocks): Use OPT_Wopenmp with gfc_warning{,_now}.

 gcc/c-family/c.opt|  4 
 gcc/c/c-parser.cc | 38 +++---
 gcc/cp/parser.cc  | 14 --
 gcc/cp/semantics.cc   | 18 ++
 gcc/doc/invoke.texi   |  7 ++-
 gcc/fortran/lang.opt  |  4 
 gcc/fortran/openmp.cc | 32 +++-
 gcc/gimplify.cc   |  4 ++--
 gcc/omp-expand.cc | 11 ++-
 gcc/omp-general.cc|  4 ++--
 gcc/omp-low.cc| 29 +++--
 gcc/omp-simd-clone.cc |  8 
 12 files changed, 103 insertions(+), 70 deletions(-)

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 3848f378de1..c3d45a6ed96 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1175,6 +1175,10 @@ Wopenacc-parallelism
 C C++ Var(warn_openacc_parallelism) Warning
 Warn about potentially suboptimal choices related to OpenACC parallelism.
 
+Wopenmp
+C ObjC C++ ObjC++ Warning Var(warn_openmp) Init(1)
+Warn about suspicious OpenMP code
+
 Wopenmp-simd
 C C++ Var(warn_openmp_simd) Warning LangEnabledBy(C C++,Wall)
 Warn if a simd directive is overridden by the vectorizer cost model.
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 371dd29557b..f493d764627 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -16071,7 +16071,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
   protected_set_expr_location (c, expr_loc);
   if (c == boolean_true_node)
 	{
-	  warning_at (expr_loc, 0,
+	  warning_at (expr_loc, OPT_Wopenmp,
 		  "% value must be positive");
 	  t = integer_one_node;
 	}
@@ -16132,7 +16132,8 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
 	SET_EXPR_LOCATION (c, expr_loc);
   if (c == boolean_true_node)
 	{
-	  warning_at (expr_loc, 0, "% value must be positive");
+	  warning_at (expr_loc, OPT_Wopenmp,
+		  "% value must be positive");
 	  t = integer_one_node;
 	}
 
@@ -16193,7 +16194,8 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list)
 	SET_EXPR_LOCATION (c, expr_loc);
   if (c == boolean_true_node)
 	{
-	  warning_at (expr_loc, 0, "% value must be positive");
+	  warning_at (expr_loc, OPT_Wopenmp,
+		  "% value must be positive");
 	  t = integer_one_node;
 	}
 
@@ -16241,7 +16243,8 @@ c_parser_omp_clause_priority (c_parser *parser, tree list)
 	SET_EXPR_LOCATION (c, expr_loc);
   if (c == boolean_true_node)
 	{
-	  warning_at (expr_loc, 0, 

[Patch,v3] OpenMP: Accept argument to depobj's destroy clause

2023-11-24 Thread Tobias Burnus

As discussed on IRC, we now go for a warning and useOEP_LEXICOGRAPHIC - at 
least until the spec issue has been solve.

[The OpenMP spec Issue 3739 tracks the open questions/issues mentioned
in this thread.] Updated patch attached. Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Accept argument to depobj's destroy clause

Since OpenMP 5.2, the destroy clause takes an depend argument as argument;
for the depobj directive, it the new argument is optional but, if present,
it must be identical to the directive's argument.

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_omp_depobj): Accept optionally an argument
	to the destroy clause.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_depobj): Accept optionally an argument
	to the destroy clause.

gcc/fortran/ChangeLog:

	* openmp.cc (gfc_match_omp_depobj): Accept optionally an argument
	to the destroy clause.

libgomp/ChangeLog:

	* libgomp.texi (5.2 Impl. Status): An argument to the destroy clause
	is now supported.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/depobj-3.c: New test.
	* gfortran.dg/gomp/depobj-3.f90: New test.

 gcc/c/c-parser.cc   | 24 ++-
 gcc/cp/parser.cc| 25 ++-
 gcc/fortran/openmp.cc   | 12 +++-
 gcc/testsuite/c-c++-common/gomp/depobj-3.c  | 47 +
 gcc/testsuite/gfortran.dg/gomp/depobj-3.f90 | 18 +++
 libgomp/libgomp.texi|  2 +-
 6 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 371dd29557b..989c0503f37 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -21605,6 +21605,9 @@ c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
  destroy
  update (dependence-type)
 
+   OpenMP 5.2 additionally:
+ destroy ( depobj )
+
dependence-type:
  in
  out
@@ -21663,7 +21666,26 @@ c_parser_omp_depobj (c_parser *parser)
 	clause = error_mark_node;
 	}
   else if (!strcmp ("destroy", p))
-	kind = OMP_CLAUSE_DEPEND_LAST;
+	{
+	  matching_parens c_parens;
+	  kind = OMP_CLAUSE_DEPEND_LAST;
+	  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+	  && c_parens.require_open (parser))
+	{
+	  tree destobj = c_parser_expr_no_commas (parser, NULL).value;
+	  if (!lvalue_p (destobj))
+		error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
+			  "% expression is not lvalue expression");
+	  else if (depobj != error_mark_node
+		   && !operand_equal_p (destobj, depobj,
+	OEP_MATCH_SIDE_EFFECTS
+	| OEP_LEXICOGRAPHIC))
+		warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), 0,
+			"the % expression %qE should be the same "
+			"as the % argument %qE", destobj, depobj);
+	  c_parens.skip_until_found_close (parser);
+	}
+	}
   else if (!strcmp ("update", p))
 	{
 	  matching_parens c_parens;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f6d088bc73f..e4e2feac486 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -43173,6 +43173,9 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
  destroy
  update (dependence-type)
 
+   OpenMP 5.2 additionally:
+ destroy ( depobj )
+
dependence-type:
  in
  out
@@ -43219,7 +43222,27 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
 	clause = error_mark_node;
 	}
   else if (!strcmp ("destroy", p))
-	kind = OMP_CLAUSE_DEPEND_LAST;
+	{
+	  kind = OMP_CLAUSE_DEPEND_LAST;
+	  matching_parens c_parens;
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+	  && c_parens.require_open (parser))
+	{
+	  tree destobj = cp_parser_assignment_expression (parser);
+	  if (depobj != error_mark_node
+		  && destobj != error_mark_node
+		  && !operand_equal_p (destobj, depobj, OEP_MATCH_SIDE_EFFECTS
+			| OEP_LEXICOGRAPHIC))
+		warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), 0,
+			"the % expression %qE should be the same "
+			"as the % argument %qE", destobj, depobj);
+	  if (!c_parens.require_close (parser))
+		cp_parser_skip_to_closing_parenthesis (parser,
+		   /*recovering=*/true,
+		   /*or_comma=*/false,
+		   /*consume_paren=*/true);
+	}
+	}
   else if (!strcmp ("update", p))
 	{
 	  matching_parens c_parens;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 2e2e23d567b..b9ac61103af 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -4731,10 +4731,20 @@ gfc_match_omp_depobj (void)
 	  goto error;
 	}
 }
-  else if (gfc_match ("destroy") == MATCH_YES)
+  else if (gfc_match ("destroy ") == MATCH_YES)
 {
+  gfc_expr *destroyobj = NULL;
   c = gfc_get_omp_clauses ();
   c->destroy = true;
+
+  

Re: [Patch] OpenMP: Accept argument to depobj's destroy clause

2023-11-23 Thread Tobias Burnus

Hi Jakub,

On 23.11.23 16:32, Jakub Jelinek wrote:

On Thu, Nov 23, 2023 at 04:21:50PM +0100, Tobias Burnus wrote:

@@ -21663,7 +21666,25 @@ c_parser_omp_depobj (c_parser *parser)
+  else if (depobj != error_mark_node
+   && !operand_equal_p (destobj, depobj,
+OEP_MATCH_SIDE_EFFECTS))

There is also OEP_LEXICOGRAPHIC which could be used in addition to that.
The question is if we want to consider say
#pragma depobj (a[++i]) destroy (a[++i])
as same or different (similarly a[foo ()] in both cases).


I don't think that we want to permit those; I think there is (a) the
question whether both expressions have to be evaluated or not and (b),
if so, in which order and (c), if the run-time result is different,
whether both have to be 'destory'ed or only one of them (which one?).

Additionally, 'destroy-var must refer to the same depend object as the
depobj argument of the construct.' cannot be fulfilled if one is
evaluated before the other and both use the same 'i' in your case.

Thus, I do not really see an argument for permitting OEP_LEXICOGRAPHIC.

I think permitting 'volatile' does make sense, in a ways, as a
hyper-careful user might actually write such code.

[I wonder whether the OpenMP wording would permit 'omp depobj(obj)
destroy(f())' with 'auto f() { return obj; }' – but I am sure we don't
want to permit it in the compiler.]

Tobias

PS: In any case, I find it confusing to require that the same
variable/lvalue-expression has to be specified twice. The (only) pro is
that for 'omp interop destroy(...)' the argument is required and for
consistency of the 'destroy' clause, an argument now must be (always)
specified. But that leads to the odd 'omp depobj(obj) destroy(obj)',
which is really ugly. (In 5.2 the arg to destroy is optional but
omitting it is deprecated; hence, in OpenMP 6.0 (TR11, TR12) the
argument must be specified twice.)

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [Patch] OpenMP: Accept argument to depobj's destroy clause

2023-11-23 Thread Tobias Burnus

Hi Jakub,

On 23.11.23 15:32, Jakub Jelinek wrote:

On Thu, Nov 23, 2023 at 03:21:41PM +0100, Tobias Burnus wrote:

I stumbled over this trivial omission which blocks some testcases.
I am not sure whether I have solved the is-same-expr most elegantly,

Answer: I didn't - as expected.

+ if (DECL_UID (t) != DECL_UID (t2))
Nothing checks that t and t2 here are decls.  Use operand_equal_p instead?


Yes – I think I can simply use this instead all the other checks. That is
the function I was looking for but couldn't find before.

(I even have use the function before for PR108545.)

I decided that volatileness is fine and using twice a volatile function is
Okay according to the spec - hence, I permit this in addition. (One can
argue about it - but as specifying both is mandatory in OpenMP 6.0, it
seems to make sense.)

Revised version attached.

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Accept argument to depobj's destroy clause

Since OpenMP 5.2, the destroy clause takes an depend argument as argument;
for the depobj directive, it the new argument is optional but, if present,
it must be identical to the directive's argument.

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_omp_depobj): Accept optionally an argument
	to the destroy clause.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_depobj): Accept optionally an argument
	to the destroy clause.

gcc/fortran/ChangeLog:

	* openmp.cc (gfc_match_omp_depobj): Accept optionally an argument
	to the destroy clause.

libgomp/ChangeLog:

	* libgomp.texi (5.2 Impl. Status): An argument to the destroy clause
	is now supported.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/depobj-3.c: New test.
	* gfortran.dg/gomp/depobj-3.f90: New test.

 gcc/c/c-parser.cc   | 23 +-
 gcc/cp/parser.cc| 24 ++-
 gcc/fortran/openmp.cc   | 15 -
 gcc/testsuite/c-c++-common/gomp/depobj-3.c  | 47 +
 gcc/testsuite/gfortran.dg/gomp/depobj-3.f90 | 18 +++
 libgomp/libgomp.texi|  2 +-
 6 files changed, 125 insertions(+), 4 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 371dd29557b..006aee3e93f 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -21605,6 +21605,9 @@ c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
  destroy
  update (dependence-type)
 
+   OpenMP 5.2 additionally:
+ destroy ( depobj )
+
dependence-type:
  in
  out
@@ -21663,7 +21666,25 @@ c_parser_omp_depobj (c_parser *parser)
 	clause = error_mark_node;
 	}
   else if (!strcmp ("destroy", p))
-	kind = OMP_CLAUSE_DEPEND_LAST;
+	{
+	  matching_parens c_parens;
+	  kind = OMP_CLAUSE_DEPEND_LAST;
+	  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+	  && c_parens.require_open (parser))
+	{
+	  tree destobj = c_parser_expr_no_commas (parser, NULL).value;
+	  if (!lvalue_p (destobj))
+		error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
+			  "% expression is not lvalue expression");
+	  else if (depobj != error_mark_node
+		   && !operand_equal_p (destobj, depobj,
+	OEP_MATCH_SIDE_EFFECTS))
+		error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
+			  "the % expression %qE must be the same as "
+			  "the % argument %qE", destobj, depobj);
+	  c_parens.skip_until_found_close (parser);
+	}
+	}
   else if (!strcmp ("update", p))
 	{
 	  matching_parens c_parens;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f6d088bc73f..1fca6bff795 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -43173,6 +43173,9 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
  destroy
  update (dependence-type)
 
+   OpenMP 5.2 additionally:
+ destroy ( depobj )
+
dependence-type:
  in
  out
@@ -43219,7 +43222,26 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
 	clause = error_mark_node;
 	}
   else if (!strcmp ("destroy", p))
-	kind = OMP_CLAUSE_DEPEND_LAST;
+	{
+	  kind = OMP_CLAUSE_DEPEND_LAST;
+	  matching_parens c_parens;
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+	  && c_parens.require_open (parser))
+	{
+	  tree destobj = cp_parser_assignment_expression (parser);
+	  if (depobj != error_mark_node
+		  && destobj != error_mark_node
+		  && !operand_equal_p (destobj, depobj, OEP_MATCH_SIDE_EFFECTS))
+		error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
+			  "the % expression %qE must be the same as "
+			  "the % argument %qE", destobj, depobj);
+	  if (!c_parens.require_close (par

[Patch] OpenMP: Accept argument to depobj's destroy clause

2023-11-23 Thread Tobias Burnus

I stumbled over this trivial omission which blocks some testcases.

I am not sure whether I have solved the is-same-expr most elegantly,
but I did loosely follow the duplicated-entry check for 'map'. As that's
a restriction to the user, we don't have to catch all and I hope the code
catches the most important violations, doesn't ICE and does not reject
valid code. At least for all real-world code it should™ work, but I
guess for lvalue expressions involving function calls it probably doesn't.

Thoughts, comments?

Tobias

PS: GCC accepts an lvalue expression in C/C++ and only a identifier
for a scalar variable in Fortran, i.e. neither array elements nor
structure components.

Which variant is right depends whether one reads OpenMP 5.1 (lvalue expr,
scalar variable) or 5.2 (variable without permitting array sections or
structure components) - whereas TR12 has the same but talks about
locator list items in one restriction. For the OpenMP mess, see spec
issue #3739.
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Accept argument to depobj's destroy clause

Since OpenMP 5.2, the destroy clause takes an depend argument as argument;
for the depobj directive, it the new argument is optional but, if present,
it must be identical to the directive's argument.

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_omp_depobj): Accept optionally an argument
	to the destroy clause.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_depobj): Accept optionally an argument
	to the destroy clause.

gcc/fortran/ChangeLog:

	* openmp.cc (gfc_match_omp_depobj): Accept optionally an argument
	to the destroy clause.

libgomp/ChangeLog:

	* libgomp.texi (5.2 Impl. Status): An argument to the destroy clause
	is now supported.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/depobj-3.c: New test.
	* gfortran.dg/gomp/depobj-3.f90: New test.

 gcc/c/c-parser.cc   | 57 ++-
 gcc/cp/parser.cc| 60 -
 gcc/fortran/openmp.cc   | 15 +++-
 gcc/testsuite/c-c++-common/gomp/depobj-3.c  | 40 +++
 gcc/testsuite/gfortran.dg/gomp/depobj-3.f90 | 18 +
 libgomp/libgomp.texi|  2 +-
 6 files changed, 188 insertions(+), 4 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 371dd29557b..378647c1a67 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -21605,6 +21605,9 @@ c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
  destroy
  update (dependence-type)
 
+   OpenMP 5.2 additionally:
+ destroy ( depobj )
+
dependence-type:
  in
  out
@@ -21663,7 +21666,59 @@ c_parser_omp_depobj (c_parser *parser)
 	clause = error_mark_node;
 	}
   else if (!strcmp ("destroy", p))
-	kind = OMP_CLAUSE_DEPEND_LAST;
+	{
+	  matching_parens c_parens;
+	  kind = OMP_CLAUSE_DEPEND_LAST;
+	  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+	  && c_parens.require_open (parser))
+	{
+	  tree destobj = c_parser_expr_no_commas (parser, NULL).value;
+	  /* OpenMP requires that the two expressions are identical; catch
+		 the most common mismatches.  */
+	  if (!lvalue_p (destobj))
+		error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
+			  "% expression is not lvalue expression");
+	  else if (depobj != error_mark_node)
+		{
+		  tree t = depobj;
+		  tree t2 = build_unary_op (EXPR_LOC_OR_LOC (destobj, c_loc),
+	ADDR_EXPR, destobj, false);
+		  if (t2 != error_mark_node)
+		t2 = build_indirect_ref (EXPR_LOC_OR_LOC (t2, c_loc),
+	 t2, RO_UNARY_STAR);
+		  while (TREE_CODE (t) == COMPONENT_REF
+			 || TREE_CODE (t) == ARRAY_REF)
+{
+		  t = TREE_OPERAND (t, 0);
+		  if (TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t))
+			{
+			  t = TREE_OPERAND (t, 0);
+			  STRIP_NOPS (t);
+			  if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+			t = TREE_OPERAND (t, 0);
+}
+		}
+		  while (TREE_CODE (t2) == COMPONENT_REF
+			 || TREE_CODE (t2) == ARRAY_REF)
+{
+		  t2 = TREE_OPERAND (t2, 0);
+		  if (TREE_CODE (t2) == MEM_REF || INDIRECT_REF_P (t2))
+			{
+			  t2 = TREE_OPERAND (t2, 0);
+			  STRIP_NOPS (t2);
+			  if (TREE_CODE (t2) == POINTER_PLUS_EXPR)
+			t2 = TREE_OPERAND (t2, 0);
+}
+		}
+		  if (DECL_UID (t) != DECL_UID (t2))
+		error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
+			  "the % expression %qE must be the same "
+			  "as the % argument %qE",
+			  destobj, depobj);
+		}
+	  c_parens.skip_until_found_close (parser);
+	}
+	}
   else if (!strcmp ("update", p))
 	{
 	  matching_parens c_parens;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 

Re: [PATCH] Fortran: fix reallocation on assignment of polymorphic variables [PR110415]

2023-11-20 Thread Tobias Burnus

Hi Andrew,

On 20.11.23 14:56, Andrew Jenner wrote:

This patch adds the testcase from PR110415 and fixes the bug.


Thanks. I can confirm experimentally that it fixes the original PR.  However, 
if I extend
the original testcase (-2), it fails with run with valgrind or when run with 
-fsanitize=address.

The array testcase (-3) seems to be fine with and without your patch.

I think it makes sense to include both extended testcases and put them under
gcc/testsuite/gfortran.dg/asan/ to ensure ASAN checks for leaks and some 
invalid memory access.

I still should have a closer look at the -ftree-dump-original and at the patch 
itself.

* * *

For the '-2' testcase, ASAN (-fsanitize=undefined) shows:

==11823==ERROR: AddressSanitizer: heap-use-after-free on address 0x60800220 
at pc 0x00405d39 bp 0x7ffcfa6eef50 sp 0x7ffcfa6eef48
WRITE of size 96 at 0x60800220 thread T0
#0 0x405d38 in __copy_MAIN___D gcc/testsuite/gfortran.dg/pr110415.f90:5
#1 0x404dc0 in MAIN__ gcc/testsuite/gfortran.dg/pr110415.f90:24
#2 0x40a82b in main gcc/testsuite/gfortran.dg/pr110415.f90:28
#3 0x7f1e2a4281af in __libc_start_call_main (/lib64/libc.so.6+0x281af) 
(BuildId: bbeee08e5f56966e641c4f3ba4ea1da9d730d0ab)
#4 0x7f1e2a428278 in __libc_start_main@@GLIBC_2.34 
(/lib64/libc.so.6+0x28278) (BuildId: bbeee08e5f56966e641c4f3ba4ea1da9d730d0ab)
#5 0x402274 in _start ../sysdeps/x86_64/start.S:115

0x60800220 is located 0 bytes inside of 96-byte region 
[0x60800220,0x60800280)
freed by thread T0 here:
#0 0x7f1e2b4daf35  (/lib64/libasan.so.8+0xdaf35) (BuildId: 
3e1694ad218c99a8b1b69231666a27df63cf19d0)
#1 0x404d1c in MAIN__ gcc/testsuite/gfortran.dg/pr110415.f90:24
#2 0x40a82b in main gcc/testsuite/gfortran.dg/pr110415.f90:28
#3 0x7f1e2a4281af in __libc_start_call_main (/lib64/libc.so.6+0x281af) 
(BuildId: bbeee08e5f56966e641c4f3ba4ea1da9d730d0ab)

previously allocated by thread T0 here:
#0 0x7f1e2b4dc03f in malloc (/lib64/libasan.so.8+0xdc03f) (BuildId: 
3e1694ad218c99a8b1b69231666a27df63cf19d0)
#1 0x4042d2 in MAIN__ gcc/testsuite/gfortran.dg/pr110415.f90:22
#2 0x40a82b in main gcc/testsuite/gfortran.dg/pr110415.f90:28
#3 0x7f1e2a4281af in __libc_start_call_main (/lib64/libc.so.6+0x281af) 
(BuildId: bbeee08e5f56966e641c4f3ba4ea1da9d730d0ab)

* * *

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
! { dg-do run }
!
! Contributed by Brad Richardson 
!
implicit none
  type, abstract :: p
integer :: a = 4
  end type p

  type, extends(p) :: c
integer :: b = 7
character(len=:), allocatable :: str, str2(:)
  end type c

  type, extends(p) :: d
integer :: ef = 7
character(len=:), allocatable :: str, str2(:)
  end type d

  class(p), allocatable :: a

  a = func()

  a = func2()

  a = func()

  deallocate(a)

contains
  function func2() result(a)
class(p), allocatable :: a
a = d()
  end function func2

  function func() result(a)
class(p), allocatable :: a

a = c()
select type(a)
type is (c)
  a%str = 'abcd'
  a%str2 = ['abcd','efgh']
end select
  end function func
end program
! { dg-do run }
!
! Contributed by Brad Richardson 
!
implicit none
  type, abstract :: p
integer :: a = 4
  end type p

  type, extends(p) :: c
integer :: b = 7
character(len=:), allocatable :: str, str2(:)
  end type c

  type, extends(p) :: d
integer :: ef = 7
character(len=:), allocatable :: str, str2(:)
  end type d

  class(p), allocatable :: a(:)

  a = func()

  a = func2()

  a = func()

  deallocate(a)

contains
  function func2() result(a)
class(p), allocatable :: a(:)
a = [d(),d()]
  end function func2

  function func() result(a)
class(p), allocatable :: a(:)

a = [c(),c(),c()]
select type(a)
type is (c)
  a(1)%str = 'abcd'
  a(2)%str = 'abc'
  a(3)%str = 'abcd4'
  a(1)%str2 = ['abcd','efgh']
  a(2)%str2 = ['bcd','fgh']
  a(3)%str2 = ['abcd6','efgh7']
end select
  end function func
end program


[patch] OpenMP: Add uses_allocators support

2023-11-20 Thread Tobias Burnus

This adds middle end support for uses_allocators, wires Fortran to use
it and add C/C++ parsing support.

This is based on Chung-Lin's patch at
https://gcc.gnu.org/pipermail/gcc-patches/2022-June/596412.html

There is a known firstprivate/private issue for C/C++, see:
https://gcc.gnu.org/PR110347 but that one is unrelated.

Tested on x86-64-gnu-linux w/o offloading; with offloading still running.

Comments, suggestions?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Add uses_allocators support

2023-11-19  Tobias Burnus  
	Chung-Lin Tang 

gcc/ChangeLog:

	* builtin-types.def (BT_FN_VOID_PTRMODE):
	(BT_FN_PTRMODE_PTRMODE_INT_PTR): Add.
	* gimplify.cc (gimplify_bind_expr): Diagnose missing
	uses_allocators clause.
	(gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses,
	gimplify_omp_workshare): Handle uses_allocators.
	* omp-builtins.def (BUILT_IN_OMP_INIT_ALLOCATOR,
	BUILT_IN_OMP_DESTROY_ALLOCATOR): Add.
	* omp-low.cc (scan_sharing_clauses):
	* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_USES_ALLOCATORS.
	* tree.cc (omp_clause_num_ops, omp_clause_code_name): Likewise.
	* tree-pretty-print.cc (dump_omp_clause): Handle it.
	* tree.h (OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR,
	OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE,
	OMP_CLAUSE_USES_ALLOCATORS_TRAITS): New.

gcc/c-family/ChangeLog:

	* c-omp.cc (c_omp_split_clauses): Hande uses_allocators.
	* c-pragma.h (enum pragma_omp_clause): Add
	PRAGMA_OMP_CLAUSE_USES_ALLOCATORS.

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_omp_clause_uses_allocators): New.
	(c_parser_omp_clause_name, c_parser_omp_all_clauses,
	OMP_TARGET_CLAUSE_MASK): Handle uses_allocators.
	* c-typeck.cc (c_finish_omp_clauses): Likewise.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_clause_uses_allocators): New.
	(cp_parser_omp_clause_name, cp_parser_omp_all_clauses,
	OMP_TARGET_CLAUSE_MASK): Handle uses_allocators.
	* semantics.cc (finish_omp_clauses): Likewise.

gcc/fortran/ChangeLog:

	* trans-array.cc (gfc_conv_array_initializer): Set PURPOSE
	when building constructor for get_initialized_tmp_var.
	* trans-openmp.cc (gfc_trans_omp_clauses): Handle uses_allocators.
	* types.def (BT_FN_VOID_PTRMODE, BT_FN_PTRMODE_PTRMODE_INT_PTR): Add.

libgomp/ChangeLog:

	* testsuite/libgomp.c++/c++.exp (check_effective_target_c,
	check_effective_target_c++): Add.
	* testsuite/libgomp.c/c.exp (check_effective_target_c,
	check_effective_target_c++): Add.
	* testsuite/libgomp.fortran/uses_allocators_2.f90: Remove 'sorry'.
	* testsuite/libgomp.c-c++-common/uses_allocators-1.c: New test.
	* testsuite/libgomp.c-c++-common/uses_allocators-2.c: New test.
	* testsuite/libgomp.c-c++-common/uses_allocators-3.c: New test.
	* testsuite/libgomp.c-c++-common/uses_allocators-4.c: New test.
	* testsuite/libgomp.fortran/uses_allocators_3.f90: New test.
	* testsuite/libgomp.fortran/uses_allocators_4.f90: New test.
	* testsuite/libgomp.fortran/uses_allocators_5.f90: New test.
	* testsuite/libgomp.fortran/uses_allocators_6.f90: New test.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/allocate-1.f90: Add uses_allocators.
	* gfortran.dg/gomp/scope-6.f90: Update dg-scan-tree-dump.
	* c-c++-common/gomp/uses_allocators-1.c: New test.
	* c-c++-common/gomp/uses_allocators-2.c: New test.
	* gfortran.dg/gomp/uses_allocators-1.f90: New test.

Co-authored-by: Chung-Lin Tang 

 gcc/builtin-types.def  |   3 +
 gcc/c-family/c-omp.cc  |   1 +
 gcc/c-family/c-pragma.h|   1 +
 gcc/c/c-parser.cc  | 216 ++-
 gcc/c/c-typeck.cc  | 105 +
 gcc/cp/parser.cc   | 237 -
 gcc/cp/semantics.cc|  95 +
 gcc/fortran/trans-array.cc |   5 +-
 gcc/fortran/trans-openmp.cc|  42 +++-
 gcc/fortran/types.def  |   3 +
 gcc/gimplify.cc| 183 +++-
 gcc/omp-builtins.def   |   4 +
 gcc/omp-low.cc |  32 +++
 .../c-c++-common/gomp/uses_allocators-1.c  |  46 
 .../c-c++-common/gomp/uses_allocators-2.c  |  33 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-1.f90  |   7 +-
 gcc/testsuite/gfortran.dg/gomp/scope-6.f90 |   2 +-
 .../gfortran.dg/gomp/uses_allocators-1.f90 |  23 ++
 gcc/tree-core.h|   3 +
 gcc/tree-pretty-print.cc   |  14 ++
 gcc/tree.cc|   2 +
 gcc/tree.h |   9 +
 libgomp/testsuite/libgomp.c++/c++.exp

Re: [PATCH v7 2/5] OpenMP/OpenACC: Rework clause expansion and nested struct handling

2023-11-14 Thread Tobias Burnus

Hi Julian,

first round of comments - I think I need a second pass as the patch is
long and complex. The depth of review also was decreasing, hence, I
assume I will spot things in later parts of the compiler.

In any case, I think the patch is a huge leap forward and very useful!

Contrary to previous iterations of the patch series, it looks as if
{1,2}/5 could be sensibly applied before {3,4,5}/5. However, those are
smaller or tiny, it should be way quicker to review them!

* * *

CROSS REFS

This patch is part of the patch set
"[PATCH v7 0/5] OpenMP/OpenACC: map clause and OMP gimplify rework"
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627895.html

This patch set in turn is required for the follow-up patch set
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/629363.html
'[PATCH 0/8] OpenMP: lvalue parsing and "declare mapper" support'

and it looks as if it would be very useful for some other WIP patches
like map+iterator.

* * *

The patch 1/5 is just an indentation patch to make the following patch
smaller - and it has been approved multiple times.

This patch can be found at
  https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627897.html
in case someone wants to read the full patch or Julian's patch-intro
comments.

* * *

I do note that all 5 patches of this patch set apply cleanly with some
fuzzy line matching, but:

WARNING: at least for this patch (2/5), code gets wrongly applied
in (c-)parser.cc - see below.

On 19.08.23 00:47, Julian Brown wrote:

This patch reworks clause expansion in the C, C++ and (to a lesser
extent) Fortran front ends for OpenMP and OpenACC mapping nodes used in
GPU offloading support.

At present a single clause may be turned into several mapping nodes,
or have its mapping type changed, in several places scattered through
the front- and middle-end.  The analysis relating to which particular
transformations are needed for some given expression has become quite hard
to follow.  Briefly, we manipulate clause types in the following places:


[...]

[As the patch is very large, I copied the interesting bits out of the patch
and comment on them - I hope that preserves enough context to be useful.]


  tree c_omp_address_inspector::get_address ()


This class member function is unused. It returns 'orig' and that member variable
is used a couple of times in the member functions - but not this function.

I think it can be removed. (I also find the name slightly misleading.)

* * *


+c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
+{
+  switch (OMP_CLAUSE_MAP_KIND (clause))
+{
+case GOMP_MAP_ALLOC:
+case GOMP_MAP_IF_PRESENT:
+case GOMP_MAP_TO:
+case GOMP_MAP_FROM:
+case GOMP_MAP_TOFROM:
+case GOMP_MAP_ALWAYS_TO:
+case GOMP_MAP_ALWAYS_FROM:
+case GOMP_MAP_ALWAYS_TOFROM:
+case GOMP_MAP_RELEASE:
+case GOMP_MAP_DELETE:
+case GOMP_MAP_FORCE_TO:
+case GOMP_MAP_FORCE_FROM:
+case GOMP_MAP_FORCE_TOFROM:
+case GOMP_MAP_FORCE_PRESENT:

Shouldn't this also include:

GOMP_MAP_ALWAYS_PRESENT_TO:
GOMP_MAP_ALWAYS_PRESENT_FROM:
GOMP_MAP_ALWAYS_PRESENT_TOFROM:
GOMP_MAP_PRESENT_ALLOC:
GOMP_MAP_PRESENT_TO:

?

* * *

+omp_expand_access_chain (tree c, tree expr, vec _tokens,
+unsigned *idx)
+{
+  using namespace omp_addr_tokenizer;
+  location_t loc = OMP_CLAUSE_LOCATION (c);
+  unsigned i = *idx;
+  tree c2 = NULL_TREE;
+  gomp_map_kind kind
+= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
+   || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+  && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
+  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
+  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
+  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
+  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
+  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM)))
+  ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH;

GOMP_MAP_ALWAYS_PRESENT_FROM  missing?

And I personally find it more readable to have
  if (...
  ...
  ...)
kind = GOMP_MAP_DETACH;
  else
kind = GOMP_MAP_ATTACH;

as in the assignment above, the lhs is in this case really far from the rhs.


* * *

I do see in omp_expand_access_chain, which is shared by C and C++, that the 
following
accesses are handled:

  ACCESS_POINTER,
  ACCESS_POINTER_OFFSET,
  ACCESS_INDEXED_ARRAY,

But not:
  ACCESS_REF_TO_POINTER,
  ACCESS_REF_TO_POINTER_OFFSET,
  ACCESS_INDEXED_REF_TO_ARRAY

Do those need to be handled as well?

SIDENOTE: As Fortran allocatable components, reference-type variables in a C++ 
class ('class', 'struct')
are automatically be copied when doing 'map(var)' - contrary to pointer members 
that need to be explicitly
be mapped (either at mapping side or via a mapper). (And contrary to Fortran 
allocatables, reference-type members
are always "there" - not like with allocatables can change from unallocated to 
allocated - with all compilations
of 

[patch] OpenMP/Fortran: Implement omp allocators/allocate for ptr/allocatables

2023-11-08 Thread Tobias Burnus

Hi all,

Comment to reviewers:
* Fortran: Except for ensuring that the version field in array descriptors
  is always set to the default (zero), the generated code should only be
  affected when -fopenmp-allocators is set, even though several files are
  touched.
* Middle-end: BUILT_IN_GOMP_REALLOC has been added - otherwise untouched.
* Otherwise, smaller libgomp changes, conditions to (de)allocation code in
  fortran/trans*.cc and and some checking updates (mostly openmp.cc)

* * *

GCC supports OpenMP's allocators, which work typically as:

  my_c_ptr = omp_alloc (byte_size, my_allocator)
  ...
  call omp_free (my_c_ptr, omp_null_allocator)

where (if called as such) the runtime has to find the used allocator in
order to handle the 'free' (and likewise: omp_realloc) correctly. libgomp
implements this by allocating a bit more bytes - and using the first bytes
to store the handle for the allocator such that 'my_c_ptr minus size of handle'
will be the address. See also OpenMP spec and:
  https://gcc.gnu.org/onlinedocs/libgomp/OMP_005fALLOCATOR.html
  https://gcc.gnu.org/onlinedocs/libgomp/Memory-Management-Routines.html
  https://gcc.gnu.org/onlinedocs/libgomp/Memory-allocation.html
and https://gcc.gnu.org/wiki/cauldron2023 (OpenMP BoF; video recordings not
yet available, slide is)


FOR FORTRAN, OpenMP permits to allocate ALLOCATABLES and POINTERS also as
follows:

  !$omp allocators allocate(allocator(my_alloc), align(128) : A)
   allocate(A(10), B)
   A = [1,2,3]   ! reallocate with same allocator
   call intent_out_function(B)  ! Has to use proper deallocator
   deallocate(A)   ! Likewise.
   ! end of scope deallocation: Likewise.

(Side remark: In 5.{1,2}, '!$omp allocate(A,B) allocator(my_alloc) align(123)'
is the syntax to use - which has nearly the same effect, except that for
non-specified variables, 'omp allocators' uses the normal Fortran allocation
while for a 'omp allocate' without a variable list uses that OpenMP allocator
for nonlisted variables.)

* * *

The problem is really that 'malloc'ed memory has to be freed/realloced by 'free'
and 'realloc' while 'omp_alloc'ed memory has to be by handled by 'omp_free'
and 'omp_realloc' - getting this wrong will nearly always crash the program-

I assume that the propagation depth is rather slow, i.e. most likely all 
deallocation
will happen in the file as the allocation, but that's not guaranteed and I bet 
that
a few "leaks" to other files are likely in every other software package.

* * *

ASSUMPTIONS for the attached implementation:

* Most OpenMP code will not use '!$omp allocators'
  (Note: Using the API routines or 'allocate' clauses on block-associated
   directives (like: omp parallel firstprivate(a) allocate(allocator(my_alloc) 
:a)')
   or 'omp allocate' for stack variables are separate and pose no problems.)

* The (de,re)allocation will not happen in a hot code

* And, if used, the number of scalar variables of this kind will be small


SOLUTION as implemented:

* All code that uses 'omp allocator' and all code that might deallocate such 
memory
  must be compiled by a special flag:
 -fopenmp-allocators
  This solves the issues:
  - Always having an overhead even if -fopenmp code does not need it
  - Permitting (de,re)allocation of such a variable from code which is not 
compiled
with -fopenmp

  While -fopenmp-allocators could be auto-enabled when 'omp allocators' shows 
up in
  a file, I decided to require it explicitly by the user in order to highlight 
that
  other files might require the same flag as thy might do (de,re)allocation on 
such
  memory.

* For ARRAYS, we fortunately can encode it in the descriptor. I (mis)use the 
version
  field for this: version = 0 means standard Fortran way while version = 1 
means using
  omp_alloc and friends.

* For SCALARS, there is no way to store this. As (see assumptions) this is 
neither in a
  hot path nor are there very many variables, we simply keep track of such 
variables in
  a separate way. (O (log2 N)) in libgomp - by keekping track of the pointer 
address in
  libgomp.


Disclaimer:
* I am not 100% sure that I have caught all corner cases for 
deallocation/reallocation;
  however, it should covers most.

* One area that is probably not fully covered is BIND(C). A Fortran actual to a 
BIND(C)
  intent(out) should work (dealloced on the caller side), once converted to a 
CFI descriptor,
  all deallocations will likely fail, be it a later intrinsic-assignment 
realloc,
  cfi_deallocate or 'deallocate' after conversion to Fortran.

  This can be fixed but requires (a) adding the how-allocated to the CFI 
descriptor but not
  as version (as that is user visible) and (b) handling it in CFI_deallocate.
  The latter will add a dependency on 'omp_free', which somehow has to be 
resolved.
  (Like weak symbols, which is likely not supported on all platforms.)

  Thus, as very special case, it has been left out - but it could be added. If 
a user
  code hits it, it should cause a 

[committed] libgfortran: Fix calloc call by swapping arg order [PR112364]

2023-11-06 Thread Tobias Burnus

See PR for a discussion whether this change is required for alignment (or 
other) reasons
(looks as if not) - or"just" to match the indented order (arg names + 
description) and
to silence a -Walloc-size warning.

Committed as r14-5148-g17df6ddcf11aef

(BTW: I don't think that it is worthwhile to backport it - the -Walloc-size 
warning is new
since r14-5059-gd880e093d92084.)

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 17df6ddcf11aef6d200305d35641a7deb2f430e1
Author: Tobias Burnus 
Date:   Mon Nov 6 11:34:31 2023 +0100

libgfortran: Fix calloc call by swapping arg order [PR112364]

The prototype of calloc is
  void *calloc(size_t nmemb, size_t size);
denoting "an array of nmemb objects, each of whose size is size." (C23)

In order to follow the meaning of the argument names and to silence
a -Walloc-size warning, this commit swaps the order of the two args
to read now:  calloc (1, sizeof (transfer_queue));

libgfortran/ChangeLog:

PR libfortran/112364
* io/async.c (enqueue_transfer, enqueue_done_id, enqueue_done,
enqueue_close): Swap 1st and 2nd arg in calloc call.

diff --git a/libgfortran/io/async.c b/libgfortran/io/async.c
index 57097438e89..8fa1f0d4ce0 100644
--- a/libgfortran/io/async.c
+++ b/libgfortran/io/async.c
@@ -262,7 +262,7 @@ init_async_unit (gfc_unit *u)
 void
 enqueue_transfer (async_unit *au, transfer_args *arg, enum aio_do type)
 {
-  transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
+  transfer_queue *tq = calloc (1, sizeof (transfer_queue));
   tq->arg = *arg;
   tq->type = type;
   tq->has_id = 0;
@@ -284,7 +284,7 @@ int
 enqueue_done_id (async_unit *au, enum aio_do type)
 {
   int ret;
-  transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
+  transfer_queue *tq = calloc (1, sizeof (transfer_queue));
 
   tq->type = type;
   tq->has_id = 1;
@@ -308,7 +308,7 @@ enqueue_done_id (async_unit *au, enum aio_do type)
 void
 enqueue_done (async_unit *au, enum aio_do type)
 {
-  transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
+  transfer_queue *tq = calloc (1, sizeof (transfer_queue));
   tq->type = type;
   tq->has_id = 0;
   LOCK (>lock);
@@ -328,7 +328,7 @@ enqueue_done (async_unit *au, enum aio_do type)
 void
 enqueue_close (async_unit *au)
 {
-  transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
+  transfer_queue *tq = calloc (1, sizeof (transfer_queue));
 
   tq->type = AIO_CLOSE;
   LOCK (>lock);


Re: [PATCH] Fortran: Fix generate_error library function fnspec

2023-11-03 Thread Tobias Burnus

On 03.11.23 13:54, Martin Jambor wrote:

when developing an otherwise unrelated patch I've discovered that the
fnspec for the Fortran library function generate_error is wrong. It is
currently ". R . R " where the first R describes the first parameter
and means that it "is only read and does not escape."  The function
itself, however, with signature:

   bool
   generate_error_common (st_parameter_common *cmp, int family, const char 
*message)

contains the following:

   /* Report status back to the compiler.  */
   cmp->flags &= ~IOPARM_LIBRETURN_MASK;

which does not correspond to the fnspec and breaks testcase
gfortran.dg/large_unit_2.f90 when my patch is applied, since it tries
to re-use the flags from before the call.

This patch replaces the "R" with "W" which stands for "specifies that
the memory pointed to by the parameter does not escape."

Bootstrapped and tested on x86_64-linux.  OK for master?


LGTM - thanks for the fix!

Tobias


2023-11-02  Martin Jambor  

 * trans-decl.cc (gfc_build_builtin_function_decls): Fix fnspec of
 generate_error.

---
  gcc/fortran/trans-decl.cc | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index a3f037bd07b..b86cfec7d49 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -3821,7 +3821,7 @@ gfc_build_builtin_function_decls (void)
  void_type_node, -2, pchar_type_node, pchar_type_node);

gfor_fndecl_generate_error = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("generate_error")), ". R . R ",
+ get_identifier (PREFIX("generate_error")), ". W . R ",
  void_type_node, 3, pvoid_type_node, integer_type_node,
  pchar_type_node);


-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH] Fortran: Fix incompatible types between INTEGER(8) and TYPE(c_ptr)

2023-10-26 Thread Tobias Burnus

Hi Paul-Antoine,

On 26.10.23 13:24, Paul-Antoine Arras wrote:

Please see the updated patch attached incorporating your input and
details below.

...

Is this latest revision ready to commit?


LGTM.

Thanks,

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH] Fortran: Fix incompatible types between INTEGER(8) and TYPE(c_ptr)

2023-10-24 Thread Tobias Burnus

Hi PA, hello all,

First, I hesitate to review/approve a patch I am involved in; Thus, I would like
if someone could have a second look.

Regarding the patch itself:


On 20.10.23 16:02, Paul-Antoine Arraswrote:

Hi all,

The attached patch fixes a bug that causes valid OpenMP declare
variant directive
and functions to be rejected with the following error (see testcase):

[...]
Error: variant ‘foo_variant’ and base ‘foo’ at (1) have incompatible
types: Type mismatch in argument 'c_bv' (INTEGER(8)/TYPE(c_ptr))

The fix consists in special-casing this situation in gfc_compare_types().
OK for mainline?

...

Subject: [PATCH] Fortran: Fix incompatible types between INTEGER(8) and
  TYPE(c_ptr)

In the context of an OpenMP declare variant directive, arguments of type C_PTR
are sometimes recognised as C_PTR in the base function and as INTEGER(8) in the
variant - or the other way around, depending on the parsing order.
This patch prevents such situation from turning into a compile error.

2023-10-20  Paul-Antoine Arras
  Tobias Burnus

gcc/fortran/ChangeLog:

  * interface.cc (gfc_compare_types): Return true in this situation.


That's a bad description. It makes sense when reading the commit log but if you
only read gcc/fortran/ChangeLog, 'this situation' is a dangling reference.


  gcc/fortran/ChangeLog.omp|  5 ++
  gcc/testsuite/ChangeLog.omp  |  4 ++


On mainline, the ChangeLog not ChangeLog.omp is used. This changelog is 
automatically
filled by the data in the commit log. Thus, no need to include it in the patch.
(Besides: It keeps getting outdated by any other commit to that file.)

As you have a commit, running the following, possibly with the commit hash as
argument (unless it is the last commit) will show that the nightly script will 
use:

./contrib/gcc-changelog/git_check_commit.py -v -p

It is additionally a good check whether you got the syntax right. (This is run
as pre-commit hook.)

* * *

Regarding the patch, I think it will work, but I wonder whether we can do
better - esp. regarding c_ptr vs. c_funptr.

I started by looking why the current code fails:


index e9843e9549c..8bd35fd6d22 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -705,12 +705,17 @@ gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
-
-  if (((ts1->type == BT_INTEGER && ts2->type == BT_DERIVED)
-   || (ts1->type == BT_DERIVED && ts2->type == BT_INTEGER))
-  && ts1->u.derived && ts2->u.derived
-  && ts1->u.derived == ts2->u.derived)


This does not work because the pointers to the derived type are different:

(gdb) p *ts1
$10 = {type = BT_INTEGER, kind = 8, u = {derived = 0x30c66b0, cl = 0x30c66b0, 
pad = 51144368}, interface = 0x0, is_c_interop = 1, is_iso_c = 0, f90_type = 
BT_VOID, deferred = false,
  interop_kind = 0x0}

(gdb) p *ts2
$11 = {type = BT_DERIVED, kind = 0, u = {derived = 0x30c2930, cl = 0x30c2930, 
pad = 51128624}, interface = 0x0, is_c_interop = 0, is_iso_c = 0, f90_type = 
BT_UNKNOWN,
  deferred = false, interop_kind = 0x0}

The reason seems to be that they are freshly created
in different namespaces. Consequently, attr.use_assoc = 1
and the namespace is different, i.e.


(gdb) p ts1->u.derived->ns->proc_name->name
$18 = 0x76ff4138 "foo"

(gdb) p ts2->u.derived->ns->proc_name->name
$19 = 0x76ffc260 "foo_variant"

* * *

Having said this, I think we can combine the current
and the modified version, i.e.


+  if ((ts1->type == BT_INTEGER && ts2->type == BT_DERIVED
+   && ts1->f90_type == BT_VOID
+   && ts2->u.derived->ts.is_iso_c
+   && ts2->u.derived->ts.u.derived->ts.f90_type == BT_VOID)
+  || (ts2->type == BT_INTEGER && ts1->type == BT_DERIVED
+   && ts2->f90_type == BT_VOID
+   && ts1->u.derived->ts.is_iso_c
+   && ts1->u.derived->ts.u.derived->ts.f90_type == BT_VOID))


See attached patch for a combined version, which checks now
whether from_intmod == INTMOD_ISO_C_BINDING and then compares
the names (to distinguish c_ptr and c_funptr). Those are unaffected
by 'use' renames, hence, we should be fine.

While in this example, the name pointers are identical, I fear that
won't hold in some more complex indirect use via module-use. Thus,
strcmp is used.

(gdb) p ts1->u.derived->name
$13 = 0x76ff4100 "c_ptr"

(gdb) p ts2->u.derived->name
$14 = 0x76ff4100 "c_ptr"

* * *

Additionally, I think it would be good to have a testcase which checks for
  c_funptr vs. c_ptr
mismatch.

Just changing c_ptr to c_funptr in the testcase (+ commenting the c_f_pointer)
prints:
  Error: variant ‘foo_variant’ and base ‘foo’ at (1) have incompatible types: 
Type mismatch in argument 'c_bv' (INTEGER(8)/TYPE(c_funptr))

I think that would b

[Patch] OpenMP/Fortran: Handle unlisted items in 'omp allocators' + exec. 'omp allocate'

2023-10-24 Thread Tobias Burnus

This patch assumes that EXEC_OMP_ALLOCATE/EXEC_OMP_ALLOCATORS is/will be later 
handled as currently
done in OG13, 
https://github.com/gcc-mirror/gcc/blob/devel/omp/gcc-13/gcc/fortran/trans-openmp.cc

Depending how we want to handle it in mainline, the patch still could make sense
- or parts should be modified, e.g. we might want to handle standard Fortran 
allocation (malloc)
and OpenMP one (GOMP_alloc) directly in trans-sstmt.cc; if so, we might want to 
skip adding another
allocate-stmt. - We probably still want to do the 'allocate' and diagnostic 
hanlding in openmp.cc
in all cases.

In any case, we surely need to handle on mainline:
* the dump-parse-tree.cc patch is surely needed and without removing
the empty entry (n->sym == NULL), it needs an additional fix in order not to 
crash.
* Rejecting coarrays in the empty-list case, which presumably makes most
  sense inside openmp.cc.

* * *

On mainline, an executable '!$omp allocate' / '!$omp allocators' stops
in trans-openmp.cc with a sorry, not yet implemented.
However, OG13 has some implementation for executable '!$omp allocate';
trying to merge mainline into OG13, I found the following issues:

* -fdump-parse-tree did not dump the clauses (trivial issue)
  (simple oversight)
* The not-specified items should be better handled
  => done now during resolution in openmp.cc.

* * *

While -fdump-tree-original can be used to test it, the "sorry" makes
it hard to write a testsuite test. Some testcases exist like
gfortran.dg/gomp/allocate-5.f90, which contains code similar to the
last example, but it is only a parse + 'sorry'-shows-up testcase.
(Well, the two new 'error:' cases can be tested and are tested but
they are more boring.)

* * *

The spec states:

For
  !$omp allocators allocate(align(4):a,b)
  allocate(a,b,c,d)
only a and b are allocated with an OpenMP allocator (→ 
omp_get_default_allocator())
and alignment of 4. - 'c' and 'd' are allocated in the normal Fortran way.

The deprecated works as follows:
  !$omp allocate(a,b) align(4)
  !$omp allocate align(16)   ! not: no list argument after 'allocate')
  allocate(a,b,c,d)
where a and b will be allocated with an alignment of 4 and the rest,
here, c and d, with the settings of the directive without argument list,
i.e. c and d are allocated with an alignment of 16.

The question is what is supposed to happen for:
  !$omp allocate(a,b) align(4)
  allocate(a,b,c,d)
Should that use the default allocator for c and d, i.e. the same as
  !$omp allocate(a,b) align(4)
  !$omp allocate
  allocate(a,b,c,d)

Or should it use the normal Fortran allocator, following what 'allocators' does?

The spec does not really tell (and that syntax is deprecated in 5.2, removed in
TR11/OpenMP 6). Thus, GCC now prints an error.  However, it would be trivial to
choose either of the other variants.

* * *

The attached patch now handles the not-specified items:
* It adds them in the last case to the list; namelist->sym == NULL
  is the no-arguments case; this item is also removed, avoiding
  n->sym == NULL special cases later on.
* For the first two cases, a new Fortran ALLOCATE statement is created,
  containing the non-treated items.

Comments, suggestions, remarks?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Handle unlisted items in 'omp allocators' + exec. 'omp allocate'

gcc/fortran/ChangeLog:

	* dump-parse-tree.cc (show_omp_node): Show clauses for
	EXEC_OMP_ALLOCATE and EXEC_OMP_ALLOCATORS.
	* openmp.cc (resolve_omp_clauses): Process nonlisted items
	for EXEC_OMP_ALLOCATE and EXEC_OMP_ALLOCATORS.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/allocate-14.f90: Add new checks.
	* gfortran.dg/gomp/allocate-5.f90: Remove items from an allocate-stmt
	that are not explicitly/implicited listed in 'omp allocate'.

 gcc/fortran/dump-parse-tree.cc |   2 +
 gcc/fortran/openmp.cc  | 112 -
 gcc/testsuite/gfortran.dg/gomp/allocate-14.f90 |  41 +
 gcc/testsuite/gfortran.dg/gomp/allocate-5.f90  |   4 +-
 4 files changed, 155 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 68122e3e6fd..1440524f971 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -2241,6 +2241,8 @@ show_omp_node (int level, gfc_code *c)
 case EXEC_OACC_CACHE:
 case EXEC_OACC_ENTER_DATA:
 case EXEC_OACC_EXIT_DATA:
+case EXEC_OMP_ALLOCATE:
+case EXEC_OMP_ALLOCATORS:
 case EXEC_OMP_ASSUME:
 case EXEC_OMP_CANCEL:
 case EXEC_OMP_CANCELLATION_POINT:
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 1cc65d7fa49..95e0aaafa58 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -7924,10 +7924,14 @@ resolve_omp_clauses 

Re: OpenMP/Fortran: Group handling of 'if' clause without and with modifier

2023-10-24 Thread Tobias Burnus

CC: fortran@ for completeness.

On 24.10.23 10:55, Thomas Schwinge wrote:

OK to push (after testing) the attached
"OpenMP/Fortran: Group handling of 'if' clause without and with modifier"?
That makes an upcoming change a bit lighter.


LGTM.

(The patch just moves some code up (in the same functions) such that
'if()' and 'if(:)' are next to each other.)

Tobias


 From a6e15fe6b08e2ced98435739506f9fc10db96a63 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge
Date: Tue, 24 Oct 2023 10:43:40 +0200
Subject: [PATCH] OpenMP/Fortran: Group handling of 'if' clause without and
  with modifier

The 'if' clause with modifier was introduced in
commit b4c3a85be96585374bf95c981ba2f602667cf5b7 (Subversion r242037)
"Partial OpenMP 4.5 fortran support", but -- in some instances -- didn't place
it next to the existing handling of 'if' clause without modifier.  Unify that;
no change in behavior.

  gcc/fortran/
  * dump-parse-tree.cc (show_omp_clauses): Group handling of 'if'
  clause without and with modifier.
  * frontend-passes.cc (gfc_code_walker): Likewise.
  * gfortran.h (gfc_omp_clauses): Likewise.
  * openmp.cc (gfc_free_omp_clauses): Likewise.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[Patch] omp_lib.f90.in: Deprecate omp_lock_hint_* for OpenMP 5.0

2023-10-19 Thread Tobias Burnus

I noticed that we only tagged half of the 5.0 deprecations in the omp_lib 
module;
this added the other half. (omp_lock_hint_* was renamed to omp_sync_hint_*.)

Currently, this patch has has no visible effect - but once we bump the OpenMP 
version
from 4.5 to 5.0, there will warnings of the those.

Comments, remarks? If not, I will commit the attached patch tomorrow.

Tobias

PS: Once the OpenMP version has been bumped (as done for testing), the warning
looks as follows:

1 | use omp_lib
  |1
Warning: Using parameter ‘omp_lock_hint_kind’ declared at (1) is deprecated 
[-Wdeprecated-declarations]

3 | print *, omp_get_nested()
  |1
Warning: Using function ‘omp_get_nested’ at (1) is deprecated 
[-Wdeprecated-declarations]

The 'omp_lock_hint_kind' warning is not ideal as it uses the declared-at 
location
and not the first-used location, which would be in line 2:

integer(omp_lock_hint_kind) :: hint
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
omp_lib.f90.in: Deprecate omp_lock_hint_* for OpenMP 5.0

The omp_lock_hint_* parameters were deprecated in favor of
omp_sync_hint_*.  While omp.h contained deprecation markers for those,
the omp_lib module only contained them for omp_{g,s}_nested.

Note: The -Wdeprecated-declarations warning will only become active once
openmp_version / _OPENMP is bumped from 201511 (4.5) to 201811 (5.0).

libgomp/ChangeLog:

	* omp_lib.f90.in: Tag omp_lock_hint_* as being deprecated when
	_OPENMP >= 201811.

diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in
index e4515271252..755c0bf16ec 100644
--- a/libgomp/omp_lib.f90.in
+++ b/libgomp/omp_lib.f90.in
@@ -904,6 +904,10 @@
 
 #if _OPENMP >= 201811
 !GCC$ ATTRIBUTES DEPRECATED :: omp_get_nested, omp_set_nested
+!GCC$ ATTRIBUTES DEPRECATED :: omp_lock_hint_kind, omp_lock_hint_none
+!GCC$ ATTRIBUTES DEPRECATED :: omp_lock_hint_uncontended, omp_lock_hint_contended
+!GCC$ ATTRIBUTES DEPRECATED :: omp_lock_hint_nonspeculative
+!GCC$ ATTRIBUTES DEPRECATED :: omp_lock_hint_speculative
 #endif
 
 #if _OPENMP >= 202011


[Patch] OpenMP: Avoid ICE with LTO and 'omp allocate (was: [Patch] Fortran: Support OpenMP's 'allocate' directive for stack vars)

2023-10-18 Thread Tobias Burnus

On 18.10.23 11:36, Jakub Jelinek wrote:

On Wed, Oct 18, 2023 at 11:12:44AM +0200, Thomas Schwinge wrote:

 +FAIL: gfortran.dg/gomp/allocate-13.f90   -O  (internal compiler error: 
tree code 'statement_list' is not supported in LTO streams)

Any references to GENERIC code in clauses etc. should have been gimplified
or cleared during gimplification, we shouldn't support STATEMENT_LIST
in LTO streaming.


We only needed the statement list as aid during the gimplify.cc handling
of GOMP_alloc/GOMP_free for Fortran. How about just remove_attribute it
in that case? As discussed, as DECL_ATTRIBUTE gets added from the left
to the DECL_CHAIN, there shouldn't be a problem of introducing shared
trees; note that 'omp allocate' itself is added per DECL, i.e. it does
not introduce sharing itself, either.

Tested with x86-64-gnu-linux.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Avoid ICE with LTO and 'omp allocate'

gcc/ChangeLog:

	* gimplify.cc (gimplify_bind_expr): Remove "omp allocate" attribute
	to avoid that auxillary statement list reaches to LTO.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/allocate-13a.f90: New test.

 gcc/gimplify.cc | 18 -
 gcc/testsuite/gfortran.dg/gomp/allocate-13a.f90 | 34 +
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 9c617c21381..22ff1075abb 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -1426,7 +1426,8 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 		  DECL_ATTRIBUTES (v)
 			= tree_cons (get_identifier ("omp allocate var"),
  build_tree_list (NULL_TREE, t),
- DECL_ATTRIBUTES (t));
+ remove_attribute ("omp allocate",
+		   DECL_ATTRIBUTES (t)));
 		  tmp = build_fold_indirect_ref (v);
 		  TREE_THIS_NOTRAP (tmp) = 1;
 		  SET_DECL_VALUE_EXPR (t, tmp);
@@ -1473,7 +1474,12 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 			 at the top, unless an allocator or size expression
 			 requires to put it afterward; note that the size is
 			 always later in generated code; for strings, no
-			 size expr but still an expr might be available.  */
+			 size expr but still an expr might be available.
+			 As LTO does not handle a statement list, 'sl' has
+			 to be removed; done so by removing the attribute.  */
+		  DECL_ATTRIBUTES (t)
+			= remove_attribute ("omp allocate",
+	DECL_ATTRIBUTES (t));
 		  tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
 		  tree_stmt_iterator e = tsi_start (sl);
 		  tree needle = NULL_TREE;
@@ -1631,16 +1637,14 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 	  && !is_global_var (t)
 	  && DECL_CONTEXT (t) == current_function_decl)
 	{
-	  tree attr;
 	  if (flag_openmp
 	  && DECL_HAS_VALUE_EXPR_P (t)
 	  && TREE_USED (t)
-	  && ((attr = lookup_attribute ("omp allocate",
-	DECL_ATTRIBUTES (t))) != NULL_TREE)
-	  && TREE_CHAIN (TREE_VALUE (attr)) == NULL_TREE)
+	  && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
 	{
 	  /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
-		 causes that the GOMP_free call is already added above.  */
+		 causes that the GOMP_free call is already added above;
+		 and "omp allocate" is removed from DECL_ATTRIBUTES.  */
 	  tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
 	  tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
 	  tmp = build_call_expr_loc (end_locus, tmp, 2, v,
diff --git a/gcc/testsuite/gfortran.dg/gomp/allocate-13a.f90 b/gcc/testsuite/gfortran.dg/gomp/allocate-13a.f90
new file mode 100644
index 000..4b297cdb4aa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/allocate-13a.f90
@@ -0,0 +1,34 @@
+! { dg-do compile { target lto } }
+! { dg-additional-options "-flto" }
+
+! Same as allocate-13.f90 but compiled with -flto.
+
+! This was failing before as the statement list,
+! used for placing the GOMP_alloc/GOMP_free leaked
+! through to LTO.
+
+module m
+  implicit none
+  !$omp requires dynamic_allocators
+contains
+subroutine f ()
+  !$omp declare target
+  integer :: var
+  !$omp allocate(var)
+  var = 5
+end
+
+subroutine h ()
+  !$omp target
+   !$omp parallel
+!$omp single
+  block
+   integer :: var2(5)
+   !$omp allocate(var2)
+   var2(1) = 7
+  end block
+!$omp end single
+   !$omp end parallel
+  !$omp end target
+end
+end module


Re: [patch] fortran/intrinsic.texi: Improve SIGNAL intrinsic entry

2023-10-17 Thread Tobias Burnus

Hi Harald,

On 17.10.23 19:02, Harald Anlauf wrote:

your latest patch - which you already pushed - removes the
intrinsic declaration of signal.


Only to 'signal' or also to 'sleep'? I have now added both in the attach
patch.

(Not yet committed.)

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
From bad72a07e572e4e0ac5ae9c25b9a234d98b1258f Mon Sep 17 00:00:00 2001
From: Tobias Burnus 
Date: Tue, 17 Oct 2023 19:35:18 +0200
Subject: [PATCH] fortran/intrinsic.texi: Add 'intrinsic' to SIGNAL example

gcc/fortran/ChangeLog:

	* intrinsic.texi (signal): Add 'intrinsic :: signal, sleep' to
	the example to make it safer.
---
 gcc/fortran/intrinsic.texi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 0db557d5a38..d1407186aea 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -13214,6 +13214,7 @@ contains
 end module
 program test_signal
   use m_handler
+  intrinsic :: signal, sleep
   call signal (12, handler_print)  ! 12 = SIGUSR2 (on some systems)
   call signal (10, 1)  ! 10 = SIGUSR1 and 1 = SIG_IGN (on some systems)
 
-- 
2.34.1



[patch] fortran/intrinsic.texi: Improve SIGNAL intrinsic entry (was: [patch] fortran/intrinsic.texi: Add 'passed by value' to signal handler)

2023-10-17 Thread Tobias Burnus

Hi Harald,

On 16.10.23 20:31, Harald Anlauf wrote:

Hi Tobias,

Am 16.10.23 um 19:11 schrieb Tobias Burnus:

OK for mainline?


I think the patch qualifies as obvious.

While at it, you might consider removing the comment a few lines below
the place you are changing,

@c TODO: What should the interface of the handler be?  Does it take
arguments?

and enhance the given example by e.g.:


Updated version attached – I will commit it later today, unless anyone
has follow-up suggestions before.

Thanks for the suggestions,

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
fortran/intrinsic.texi: Improve SIGNAL intrinsic entry

gcc/fortran/ChangeLog:

	* intrinsic.texi (signal): Mention that the argument
	passed to the signal handler procedure is passed by reference.
	Extend example.

diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 6c7ad03a02c..fe446fc8a9d 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -13168,10 +13168,10 @@ end program test_sign
 @table @asis
 @item @emph{Description}:
 @code{SIGNAL(NUMBER, HANDLER [, STATUS])} causes external subroutine
-@var{HANDLER} to be executed with a single integer argument when signal
-@var{NUMBER} occurs.  If @var{HANDLER} is an integer, it can be used to
-turn off handling of signal @var{NUMBER} or revert to its default
-action.  See @code{signal(2)}.
+@var{HANDLER} to be executed with a single integer argument passed by
+value when signal @var{NUMBER} occurs.  If @var{HANDLER} is an integer,
+it can be used to turn off handling of signal @var{NUMBER} or revert to
+its default action.  See @code{signal(2)}.
 
 If @code{SIGNAL} is called as a subroutine and the @var{STATUS} argument
 is supplied, it is set to the value returned by @code{signal(2)}.
@@ -13197,19 +13197,25 @@ Subroutine, function
 @item @var{STATUS} @tab (Optional) @var{STATUS} shall be a scalar
 integer. It has @code{INTENT(OUT)}.
 @end multitable
-@c TODO: What should the interface of the handler be?  Does it take arguments?
 
 @item @emph{Return value}:
 The @code{SIGNAL} function returns the value returned by @code{signal(2)}.
 
 @item @emph{Example}:
 @smallexample
+module m_handler
+contains
+  ! POSIX.1-2017:  void (*func)(int)
+  subroutine handler_print(signum) bind(C)
+use iso_c_binding, only: c_int
+integer(c_int), value :: signum
+print *, 'handler_print invoked with signum =', signum
+  end subroutine
+end module
 program test_signal
-  intrinsic signal
-  external handler_print
-
-  call signal (12, handler_print)
-  call signal (10, 1)
+  use m_handler
+  call signal (12, handler_print)  ! 12 = SIGUSR3 (on some systems)
+  call signal (10, 1)  ! 10 = SIGUSR1 and 1 = SIG_IGN (on some systems)
 
   call sleep (30)
 end program test_signal


[patch] fortran/intrinsic.texi: Add 'passed by value' to signal handler

2023-10-16 Thread Tobias Burnus

Yesterday, someone was confused because the signal handler did not work.

It turned out that the created Fortran procedure used as handler used
pass by reference - and 'signal' passed the it by value.

This patch adds the 'passed by value' to the wording:

"@var{HANDLER} to be executed with a single integer argument passed by
value"

OK for mainline?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
fortran/intrinsic.texi: Add 'passed by value' to signal handler

gcc/fortran/ChangeLog:

	* intrinsic.texi (signal): Mention that the argument
	passed to the signal handler procedure is passed by reference.

diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 6c7ad03a02c..3620209e00a 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -13168,10 +13168,10 @@ end program test_sign
 @table @asis
 @item @emph{Description}:
 @code{SIGNAL(NUMBER, HANDLER [, STATUS])} causes external subroutine
-@var{HANDLER} to be executed with a single integer argument when signal
-@var{NUMBER} occurs.  If @var{HANDLER} is an integer, it can be used to
-turn off handling of signal @var{NUMBER} or revert to its default
-action.  See @code{signal(2)}.
+@var{HANDLER} to be executed with a single integer argument passed by
+value when signal @var{NUMBER} occurs.  If @var{HANDLER} is an integer,
+it can be used to turn off handling of signal @var{NUMBER} or revert to
+its default action.  See @code{signal(2)}.
 
 If @code{SIGNAL} is called as a subroutine and the @var{STATUS} argument
 is supplied, it is set to the value returned by @code{signal(2)}.


Re: [Patch] Fortran: Support OpenMP's 'allocate' directive for stack vars

2023-10-13 Thread Tobias Burnus

On 13.10.23 13:01, Jakub Jelinek wrote:

On Tue, Oct 10, 2023 at 06:46:35PM +0200, Tobias Burnus wrote:
+++ b/gcc/gimplify.cc

@@ -1400,23 +1400,53 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
+  else if (errorcount
+   || (align == NULL_TREE
+   && alloc != NULL_TREE
+   && integer_onep (alloc)))
+DECL_ATTRIBUTES (t) = remove_attribute ("omp allocate",
+DECL_ATTRIBUTES (t));

Probably already preexisting, by I wonder how safe remove_attribute is.
Aren't attributes shared in some cases
(like __attribute__((attr1, attr2, attr3)) int a, b, c, d;)?


I think there should be no problem – new attributes get added as:

DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
   t, DECL_ATTRIBUTES (var));

Thus, attr = DECL_ATTRIBUTES (var) is not shared, even if
TREE_CHAIN (attr) might be shared.

Thus, as long as new attributes get added at the head of the chain,
there should be no issue. And "omp allocate" is added once per decl
and is therefore not shared - removing might create again a shared
tree, but any following 'tree_cons' will again unshare it.

I think in your case, there would be indeed a problem when doing:
  'tree attr = remove_attr (...("attr2") ...)'
as this would remove "attr2" for 4 decls.

* * *

However, as 'omp allocate' is not used later on, I also do not need
to remove it.

=> Updated patch attached + interdiff for gimplify.cc attached.

Changes:
* Condition now the same as previously
* Keep 'omp allocate' also for DECL_VALUE_EXPR variable
* Add assert that we either have Fortran's expression the GOMP_FREE
  location - or a DECL_VALUE_EXPR.
* Make use of the assertion by keeping the HAS_DECL_VALUE expr below;
  this avoids adding an align/allocator == default check.
  => same code as old code, except for creating + using 'v' variable
  and adding a clobber.

* * *


Otherwise LGTM (though, I didn't spot anything about allocatables in the
patch, am I just looking wrong or are they still unsupported)?


It's unsupported – albeit Chung-Lin has some patch for it. The code path
is completely different. It already starts by 'omp allocators' (+
legacy: 'omp allocate') being not declarative but executable and
associated with a Fortran 'allocate'  statement and ...

Sorry for being slow - but I keep getting distracted by other tasks ...

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
diff -u b/gcc/gimplify.cc b/gcc/gimplify.cc
--- b/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -1400,13 +1400,10 @@
 			  "region must specify an % clause", t);
 	  /* Skip for omp_default_mem_alloc (= 1),
 		 unless align is present. */
-	  else if (errorcount
-		   || (align == NULL_TREE
-			   && alloc != NULL_TREE
-			   && integer_onep (alloc)))
-		DECL_ATTRIBUTES (t) = remove_attribute ("omp allocate",
-			DECL_ATTRIBUTES (t));
-	  else
+	  else if (!errorcount
+		   && (align != NULL_TREE
+			   || alloc == NULL_TREE
+			   || !integer_onep (alloc)))
 		{
 		  /* Fortran might already use a pointer type internally;
 		 use that pointer except for type(C_ptr) and type(C_funptr);
@@ -1426,10 +1423,10 @@
 		  tmp = build_pointer_type (type);
 		  v = create_tmp_var (tmp, get_name (t));
 		  DECL_IGNORED_P (v) = 0;
-		  tmp = remove_attribute ("omp allocate", DECL_ATTRIBUTES (t));
 		  DECL_ATTRIBUTES (v)
 			= tree_cons (get_identifier ("omp allocate var"),
- build_tree_list (NULL_TREE, t), tmp);
+ build_tree_list (NULL_TREE, t),
+ DECL_ATTRIBUTES (t));
 		  tmp = build_fold_indirect_ref (v);
 		  TREE_THIS_NOTRAP (tmp) = 1;
 		  SET_DECL_VALUE_EXPR (t, tmp);
@@ -1461,6 +1458,11 @@
 		  tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
 	 fold_convert (TREE_TYPE (v), tmp));
 		  gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
+		  /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
+		 and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
+		 is set, using in a condition much further below.  */
+		  gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
+			  || TREE_CHAIN (TREE_VALUE (attr)));
 		  if (TREE_CHAIN (TREE_VALUE (attr)))
 		{
 		  /* Fortran is special as it does not have properly nest
@@ -1631,14 +1633,15 @@
 	{
 	  tree attr;
 	  if (flag_openmp
+	  && DECL_HAS_VALUE_EXPR_P (t)
 	  && TREE_USED (t)
 	  && ((attr = lookup_attribute ("omp allocate",
 	DECL_ATTRIBUTES (t))) != NULL_TREE)
 	  

Re: PR fortran/39627 [meta-bug] Fortran 2008 support

2023-10-13 Thread Tobias Burnus

On 13.10.23 08:31, Richard Biener wrote:

On Thu, Oct 12, 2023 at 6:54 PM Paul Richard Thomas
  wrote:

I have posted the version 4 of Ian Chivers and Jane Sleightholme's F2008 
compliance table as an attachment to PR39627.

...

I am halfway through the F2018 table and will post it on PR85836 when I have 
done as much as I can.

Btw, C++ hashttps://gcc.gnu.org/projects/cxx-status.html  on the main
web pages (though I needed to use google to find it,
discoverability on our webpage isn't too great :/).


Likewise albeit slightly differently for OpenMP,
https://gcc.gnu.org/projects/gomp/#implementation-status

I think we link the C++ page from time to time in release notes at
gcc-*/changes.html.

For Fortran, we also use the wiki – and I do note that we do have a
F2018 page, but not yet a Fortran2023 one:

https://gcc.gnu.org/wiki/Fortran2003Status

https://gcc.gnu.org/wiki/Fortran2008Status

https://gcc.gnu.org/wiki/Fortran2018Status

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[Patch] Fortran: Support OpenMP's 'allocate' directive for stack vars

2023-10-10 Thread Tobias Burnus

The attached patch adds 'omp allocate' support for stack/automatic variables
variables for Fortran.

I had originally a pure FE version for Fortran, which failed with 
'defaultmap'/'default';
I then thought I could simply piggyback on the existing C/C++ support.

But it turns out that Fortran is completely different, e.g. there is often no 
BIND_EXPR
but just some (scoped / try-final-expr) code inside of it, i.e. the scope of 
the BIND_EXPR
has no relation to where GOMP_alloc has to be added. (GOMP_free is less 
critical, except
that a longer lifetime might cause memory constraints.)

Thus, RFC:
- Is the current scheme okay or should me move moved to the FE
  there is not that much happening at the ME?
- Should for the one 'if (lang_GNU_Fortran () ...' condition a lang hook
  be introduced?

Any other suggestions?

ALSO: I decided that the wording permits 'type(c_ptr)', 'type(c_funptr)' as 
they are
rather normal variables (of opaque type) in the Fortran sense. I decided that 
we do
not want to support EQUIVALENCE, Cray pointers, COMMON blocks ever (even though 
the
first to surely could be made to work, the latter - maybe.)
I also reject coarrays as it is really incompatible for allocate/allocators; for
the 'allocate' clause, that's different and permitted (just used for 
privatization).

Thoughts, suggestions?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
Fortran: Support OpenMP's 'allocate' directive for stack vars

gcc/fortran/ChangeLog:

	* gfortran.h (ext_attr_t): Add omp_allocate flag.
	* match.cc (gfc_free_omp_namelist): Void deleting same
	u2.allocator multiple times now that a sequence can use
	the same one.
	* openmp.cc (gfc_match_omp_clauses, gfc_match_omp_allocate): Use
	same allocator expr multiple times.
	(is_predefined_allocator): Make static.
	(gfc_resolve_omp_allocate): Update/extend restriction checks;
	remove sorry message.
	(resolve_omp_clauses): Reject corarrays in allocate/allocators
	directive.
	* parse.cc (check_omp_allocate_stmt): Permit procedure pointers
	here (rejected later) for less mislreading diagnostic.
	* trans-array.cc (gfc_trans_auto_array_allocation): Propagate
	size for GOMP_alloc and location to which it should be added to.
	* trans-decl.cc (gfc_trans_deferred_vars): Handle 'omp allocate'
	for stack variables; sorry for static variables/common blocks.
	* trans-openmp.cc (gfc_trans_omp_clauses): Evaluate 'allocate'
	clause's allocator only once; fix adding expressions to the
	block.
	(gfc_trans_omp_single): Pass a block to gfc_trans_omp_clauses.

gcc/ChangeLog:

	* gimplify.cc (gimplify_bind_expr): Handle Fortran's
	'omp allocate' for stack variables.

libgomp/ChangeLog:

	* libgomp.texi:
	* testsuite/libgomp.fortran/allocate-5.f90: New test.
	* testsuite/libgomp.fortran/allocate-6.f90: New test.
	* testsuite/libgomp.fortran/allocate-7.f90: New test.
	* testsuite/libgomp.fortran/allocate-8.f90: New test.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/allocate-14.c: Fix directive name.
	* c-c++-common/gomp/allocate-15.c: Likewise.
	* c-c++-common/gomp/allocate-9.c: Fix comment typo.
	* gfortran.dg/gomp/allocate-4.f90: Remove sorry dg-error.
	* gfortran.dg/gomp/allocate-7.f90: Likewise.
	* gfortran.dg/gomp/allocate-10.f90: New test.
	* gfortran.dg/gomp/allocate-11.f90: New test.
	* gfortran.dg/gomp/allocate-12.f90: New test.
	* gfortran.dg/gomp/allocate-13.f90: New test.
	* gfortran.dg/gomp/allocate-14.f90: New test.
	* gfortran.dg/gomp/allocate-15.f90: New test.
	* gfortran.dg/gomp/allocate-8.f90: New test.
	* gfortran.dg/gomp/allocate-9.f90: New test.

 gcc/fortran/gfortran.h   |   1 +
 gcc/fortran/match.cc |   9 +-
 gcc/fortran/openmp.cc|  62 +++-
 gcc/fortran/parse.cc |   8 +-
 gcc/fortran/trans-array.cc   |  28 +-
 gcc/fortran/trans-decl.cc| 121 
 gcc/fortran/trans-openmp.cc  |  77 +++--
 gcc/gimplify.cc  | 173 +---
 gcc/testsuite/c-c++-common/gomp/allocate-14.c|   2 +-
 gcc/testsuite/c-c++-common/gomp/allocate-15.c|   2 +-
 gcc/testsuite/c-c++-common/gomp/allocate-9.c |   2 +-
 gcc/testsuite/gfortran.dg/gomp/allocate-10.f90   |  74 +
 gcc/testsuite/gfortran.dg/gomp/allocate-11.f90   |  33 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-12.f90   |  24 ++
 gcc/testsuite/gfortran.dg/gomp/allocate-13.f90   |  25 ++
 gcc/testsuite/gfortran.dg/gomp/allocate-14.f90   |  95 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-15.f90   |  38 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-4.f90|   4 +-
 gcc/testsuite/gfortran.dg/gomp/allocate-7.f90|  10 -
 gcc/testsuite/gfortran.dg/gomp/allocate-8.f90|  29 ++
 

[Patch] Fortran/OpenMP: Fix handling of strictly structured blocks

2023-10-07 Thread Tobias Burnus

Strictly structured blocks are '!$omp ' directly
followed by 'BLOCK ... END BLOCK', i.e. a Fortran block construct.

I did run into this issue because 'integer :: n; n = 5; !$omp ...;
block; integer :: A(n)' was not accepted.

Well, it turned out that was because the BLOCK handling was not quite right.

In an unrelated patch, I got an ICE for an empty labelled BLOCK - but
only without -fopenmp. I was not quite sure that we had a testcase for
it - my 'grep'  attempt did not find one but we use plenty of BLOCK.
Hence, I added another BLOCK testcase.

Comments, remarks, suggestions?

If not, I will later commit it.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
Fortran/OpenMP: Fix handling of strictly structured blocks

For strictly structured blocks, a BLOCK was created but the code
was placed after the block the outer structured block. Additionally,
labelled blocks were mishandled. As the code is now properly in a
BLOCK, it solves additional issues.

gcc/fortran/ChangeLog:

	* parse.cc (parse_omp_structured_block): Make the user code end
	up inside of BLOCK construct for strictly structured blocks;
	fix fallout for 'section' and 'teams'.
	* openmp.cc (resolve_omp_target): Fix changed BLOCK handling
	for teams in target checking.

libgomp/ChangeLog:

	* testsuite/libgomp.fortran/strictly-structured-block-1.f90: New test.

gcc/testsuite/ChangeLog:

	* gfortran.dg/block_17.f90: New test.
	* gfortran.dg/gomp/strictly-structured-block-5.f90: New test.

 gcc/fortran/openmp.cc  |  2 +
 gcc/fortran/parse.cc   | 22 +--
 gcc/testsuite/gfortran.dg/block_17.f90 |  9 +++
 .../gomp/strictly-structured-block-5.f90   | 77 ++
 .../strictly-structured-block-1.f90| 22 +++
 5 files changed, 127 insertions(+), 5 deletions(-)

diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index dc0c8013c3d..79b5ae0e4bd 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -11245,6 +11245,8 @@ resolve_omp_target (gfc_code *code)
   if (!code->ext.omp_clauses->contains_teams_construct)
 return;
   gfc_code *c = code->block->next;
+  if (c->op == EXEC_BLOCK)
+c = c->ext.block.ns->code;
   if (code->ext.omp_clauses->target_first_st_is_teams
   && ((GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
 	  || (c->op == EXEC_BLOCK
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 58386805ffe..444baf42cbd 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -5814,7 +5814,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
 {
   gfc_statement st, omp_end_st, first_st;
   gfc_code *cp, *np;
-  gfc_state_data s;
+  gfc_state_data s, s2;
 
   accept_statement (omp_st);
 
@@ -5915,13 +5915,21 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
   gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C");
 
   my_ns = gfc_build_block_ns (gfc_current_ns);
-  gfc_current_ns = my_ns;
-  my_parent = my_ns->parent;
-
   new_st.op = EXEC_BLOCK;
   new_st.ext.block.ns = my_ns;
   new_st.ext.block.assoc = NULL;
   accept_statement (ST_BLOCK);
+
+  push_state (, COMP_BLOCK, my_ns->proc_name);
+  gfc_current_ns = my_ns;
+  my_parent = my_ns->parent;
+  if (omp_st == ST_OMP_SECTIONS
+	  || omp_st == ST_OMP_PARALLEL_SECTIONS)
+	{
+	  np = new_level (cp);
+	  np->op = cp->op;
+	}
+
   first_st = next_statement ();
   st = parse_spec (first_st);
 }
@@ -5937,6 +5945,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
   case ST_OMP_TEAMS_LOOP:
 	{
 	  gfc_state_data *stk = gfc_state_stack->previous;
+	  if (stk->state == COMP_OMP_STRICTLY_STRUCTURED_BLOCK)
+	stk = stk->previous;
 	  stk->tail->ext.omp_clauses->target_first_st_is_teams = true;
 	  break;
 	}
@@ -6035,8 +6045,10 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
   else if (block_construct && st == ST_END_BLOCK)
 	{
 	  accept_statement (st);
+	  gfc_current_ns->code = gfc_state_stack->head;
 	  gfc_current_ns = my_parent;
-	  pop_state ();
+	  pop_state ();  /* Inner BLOCK */
+	  pop_state ();  /* Outer COMP_OMP_STRICTLY_STRUCTURED_BLOCK */
 
 	  st = next_statement ();
 	  if (st == omp_end_st)
diff --git a/gcc/testsuite/gfortran.dg/block_17.f90 b/gcc/testsuite/gfortran.dg/block_17.f90
new file mode 100644
index 000..6ab3106ebd0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/block_17.f90
@@ -0,0 +1,9 @@
+subroutine foo()
+  block
+  end block
+end
+
+subroutine bar()
+  my_name: block
+  end block my_name
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-5.f90 

Re: Test with an lto-build of libgfortran.

2023-09-28 Thread Tobias Burnus

(replace gcc@ by gcc-patches@; see
https://gcc.gnu.org/pipermail/gcc/2023-September/242591.html
and other emails in that thread)

On 28.09.23 11:51, Jakub Jelinek wrote:

On Thu, Sep 28, 2023 at 09:29:02AM +0200, Tobias Burnus wrote:

On 28.09.23 08:25, Richard Biener via Fortran wrote:


This particular place in libgfortran has

/* write_z, which calls xtoa_big, is called from transfer.c,
   formatted_transfer_scalar_write.  There it is passed the kind as
   argument, which means a maximum of 16.  The buffer is large
   enough, but the compiler does not know that, so shut up the
   warning here.  */

...

I have replaced it now by the assert that "len <= 16", i.e.
+  if (len > 16)
+__builtin_unreachable ();

Is it just that in correct programs len can't be > 16, or that it is really
impossible for it being > 16?  I mean, we have that artificial kind 17 for
powerpc which better should be turned into length of 16, but isn't e.g.
_gfortran_transfer_integer etc.


My understanding is that kind=17 only pops up on PowerPC
for REAL variables as they represent __float128 in multiple ways.

Having said that, the current call tree is:

* xtoa_big: that's where the warning suppression
  was replaced by the unreachable.

* Only caller is 'write_z' with calls it by passing its
  last argument ('len') as last argument ('len')

* "internal_proto(write_z)" implies that it is not called from
  outside libgfortran. The internal only caller is:

*  formatted_transfer_scalar_write, which calls it as:

case FMT_Z:
  ...
#ifdef HAVE_GFC_REAL_17
  if (type == BT_REAL && kind == 17)
kind = 16;
#endif
  write_z (dtp, f, p, kind);

I am not aware of any logigal/integer/real(+comples)/character kind > 16,
except for this PPC one. And complex numbers are pairs of BT_REAL.

Thus, I think that patch should be fine - except:


Does anything error earlier if it is larger?  I mean, say user calling
_gfortan_transfer_integer by hand with kind 1024?


I think this will fail. We have various ways to deal with this in libgfortran;
I see some cases where the switch "default:" sets the length to 0; we have
other places where we use an "assert", I think we have other places were
we run into UB.

Thus, one option would be to either 'assert(len <= 16)' or
'assert((size_t)len < GFC_OTOA_BUF_SIZE - 1)' instead.

Or we could handle it as len=0 and silently ignore the output or ...

I am fine with either of the many options - except that I like something
explicit involving 'len' and a comparison (unreachable, assert, regarding as 
len = 0)
better than the existing warning suppression which is too indirect for
me. (Besides: it does not work for LTO.) Preferences? Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: Test with an lto-build of libgfortran.

2023-09-28 Thread Tobias Burnus

Hi all,

the following works for me. I have only tried a normal build (where it
does silence the same warning) and not an LTO build and I just believed
the comment - see attached patch. Comments?

On 28.09.23 08:25, Richard Biener via Fortran wrote:


This particular place in libgfortran has

   /* write_z, which calls xtoa_big, is called from transfer.c,
  formatted_transfer_scalar_write.  There it is passed the kind as
  argument, which means a maximum of 16.  The buffer is large
  enough, but the compiler does not know that, so shut up the
  warning here.  */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
   *q = '\0';
#pragma GCC diagnostic pop

so obviously the #pragma doesn't survive through LTO.  Somehow I think
this is a known bug, but maybe I misremember (I think we are not streaming
any of the ad-hoc location parts).


I have replaced it now by the assert that "len <= 16", i.e.

+  if (len > 16)
+__builtin_unreachable ();

Build + tested on x86-64-gnu-linux
Comment? OK for mainline?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
libgfortran: Use __builtin_unreachable() not -Wno-stringop-overflow to silence warning

libgfortran/
	* io/write.c (xtoa_big): Change a 'GCC diagnostic ignored
	"-Wstringop-overflow"' to an assumption (via __builtin_unreachable).

 libgfortran/io/write.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index 5d47a6d25f7..00c8fd2e288 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -1179,6 +1179,15 @@ xtoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
   uint8_t h, l;
   int i;
 
+  /* write_z, which calls xtoa_big, is called from transfer.c,
+ formatted_transfer_scalar_write.  There it is passed the kind as
+ 'len' argument, which means a maximum of 16.  The buffer is large
+ enough, but the compiler does not know that, so shut up the
+ warning here.  */
+
+  if (len > 16)
+__builtin_unreachable ();
+
   q = buffer;
 
   if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
@@ -1212,15 +1221,7 @@ xtoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
 	}
 }
 
-  /* write_z, which calls xtoa_big, is called from transfer.c,
- formatted_transfer_scalar_write.  There it is passed the kind as
- argument, which means a maximum of 16.  The buffer is large
- enough, but the compiler does not know that, so shut up the
- warning here.  */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstringop-overflow"
   *q = '\0';
-#pragma GCC diagnostic pop
 
   if (*n == 0)
 return "0";


Re: [PATCH] fortran: Rename TRUE/FALSE to true/false in *.cc files

2023-08-25 Thread Tobias Burnus

On 25.08.23 10:26, Uros Bizjak via Gcc-patches wrote:

gcc/fortran/ChangeLog:

 * match.cc (gfc_match_equivalence): Rename TRUE/FALSE to true/false.
 * module.cc (check_access): Ditto.
 * primary.cc (match_real_constant): Ditto.
 * trans-array.cc (gfc_trans_allocate_array_storage): Ditto.
 (get_array_ctor_strlen): Ditto.
 * trans-common.cc (find_equivalence): Ditto.
 (add_equivalences): Ditto.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
OK for master?


OK. Not really necessary but it makes the code more consistent.

(We already heavily use true/false (5000+ times) and the patch changes
the remaining 11 TRUE/FALSE.)

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: Help with fortran pointer ans OpenACC

2023-08-23 Thread Tobias Burnus

Hi,

On 23.08.23 12:19, Patrick Begou via Fortran wrote:

For several days I have some trouble with OpenACC offloading and
fortran pointers. I'm testing with a very small peace of code to
investigate but I do not progress for several days and I need your help.

Could someone give me advices or a small explanation on what I have
not understood there ?


First, for debugging, using -fdump-tree-original -fdump-tree-gimple
-fdump-tree-omplower and looking at the file .* might
help - grep for '#pragma'; this shows the internal representation
(incomplete) in a C like output. That's how I spotted the issue below.

* * *

For gfortran, the issue is:

!$acc parallel loop collapse(2) default(present) if(runongpu)

It works if you add a "present(current)" → see also newly filed
https://gcc.gnu.org/PR16

gfortran seems to follow - but not completely - the spec:

Quoting from OpenACC 3.2: "2.6.2 Variables with Implicitly Determined
Data Attributes":

"A scalar variable will be treated as if it appears either:

* In a copy clause if the compute construct is a kernels construct.
* In a firstprivate clause otherwise.

Note: Any default(none) clause visible at the compute construct applies
to both aggregate and scalar variables. However, any default(present)
clause visible at the compute construct applies only to aggregate
variables."

However, the glossary defines:

"Aggregate variables – a variable of any non-scalar datatype, including
array or composite variables.
In Fortran, this includes any variable with allocatable or pointer
attribute and character variables."

And, as you have a (scalar) Fortran pointer, the following should have
applied instead:

"An aggregate variable will be treated as if it appears either:
• In a present clause if there is a default(present) clause visible at
the compute construct.
• In a copy clause otherwise."

* * *

Thus: It looks as if your program is valid, adding 'present(current)'
will fix it for gfortran (and Cray?), 'default(...)' and implicit
mapping is confusing, and there is now a gfortran PR to track this
issue: https://gcc.gnu.org/PR16

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[committed] OpenMP/Fortran: Extend reject code between target + teams [PR71065, PR110725] (was: Re: [patch] OpenMP/Fortran: Reject declarations between target + teams (was: [Patch] OpenMP/Fortran: Rej

2023-07-27 Thread Tobias Burnus

Yet another omission, the flag was not properly set for deeply buried
'omp teams' as I stopped too early when walking up the stack.

Now fixed by commit r14-2826-g081e25d3cfd86c

* * *

This was found when 'repairing' the feature on the OG13
(devel/omp/gcc-13) branch for metadirectives, cf. the second attached
patch, applied after cherry-picking the mainline patch.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 081e25d3cfd86c4094999ded0bbe99b91762013c
Author: Tobias Burnus 
Date:   Thu Jul 27 18:14:11 2023 +0200

OpenMP/Fortran: Extend reject code between target + teams [PR71065, PR110725]

The previous version failed to diagnose when the 'teams' was nested
more deeply inside the target region, e.g. inside a DO or some
block or structured block.

PR fortran/110725
PR middle-end/71065

gcc/fortran/ChangeLog:

* openmp.cc (resolve_omp_target): Minor cleanup.
* parse.cc (decode_omp_directive): Find TARGET statement
also higher in the stack.

gcc/testsuite/ChangeLog:

* gfortran.dg/gomp/teams-6.f90: Extend.

diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 52eeaf2d4da..2952cd300ac 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -10666,15 +10666,14 @@ resolve_omp_target (gfc_code *code)
 
   if (!code->ext.omp_clauses->contains_teams_construct)
 return;
+  gfc_code *c = code->block->next;
   if (code->ext.omp_clauses->target_first_st_is_teams
-  && ((GFC_IS_TEAMS_CONSTRUCT (code->block->next->op)
-	   && code->block->next->next == NULL)
-	  || (code->block->next->op == EXEC_BLOCK
-	  && code->block->next->next
-	  && GFC_IS_TEAMS_CONSTRUCT (code->block->next->next->op)
-	  && code->block->next->next->next == NULL)))
+  && ((GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
+	  || (c->op == EXEC_BLOCK
+	  && c->next
+	  && GFC_IS_TEAMS_CONSTRUCT (c->next->op)
+	  && c->next->next == NULL)))
 return;
-  gfc_code *c = code->block->next;
   while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
 c = c->next;
   if (c)
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index aa6bb663def..e797402b59f 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -1318,32 +1318,27 @@ decode_omp_directive (void)
 case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
 case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
 case ST_OMP_TEAMS_LOOP:
-  if (gfc_state_stack->previous && gfc_state_stack->previous->tail)
-	{
-	  gfc_state_data *stk = gfc_state_stack;
-	  do {
-	   stk = stk->previous;
-	 } while (stk && stk->tail && stk->tail->op == EXEC_BLOCK);
-	  if (stk && stk->tail)
-	switch (stk->tail->op)
-	  {
-	  case EXEC_OMP_TARGET:
-	  case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
-	  case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
-	  case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
-	  case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
-	  case EXEC_OMP_TARGET_TEAMS_LOOP:
-	  case EXEC_OMP_TARGET_PARALLEL:
-	  case EXEC_OMP_TARGET_PARALLEL_DO:
-	  case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
-	  case EXEC_OMP_TARGET_PARALLEL_LOOP:
-	  case EXEC_OMP_TARGET_SIMD:
-		stk->tail->ext.omp_clauses->contains_teams_construct = 1;
-		break;
-	  default:
-	break;
-	  }
-	}
+  for (gfc_state_data *stk = gfc_state_stack->previous; stk;
+	   stk = stk->previous)
+	if (stk && stk->tail)
+	  switch (stk->tail->op)
+	{
+	case EXEC_OMP_TARGET:
+	case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
+	case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+	case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+	case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+	case EXEC_OMP_TARGET_TEAMS_LOOP:
+	case EXEC_OMP_TARGET_PARALLEL:
+	case EXEC_OMP_TARGET_PARALLEL_DO:
+	case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+	case EXEC_OMP_TARGET_PARALLEL_LOOP:
+	case EXEC_OMP_TARGET_SIMD:
+	  stk->tail->ext.omp_clauses->contains_teams_construct = 1;
+	  break;
+	default:
+	  break;
+	}
   break;
 case ST_OMP_ERROR:
   if (new_st.ext.omp_clauses->at != OMP_AT_EXECUTION)
diff --git a/gcc/testsuite/gfortran.dg/gomp/teams-6.f90 b/gcc/testsuite/gfortran.dg/gomp/teams-6.f90
index be453f27f40..0bd7735e738 100644
--- a/gcc/testsuite/gfortran.dg/gomp/teams-6.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/teams-6.f90
@@ -37,6

[patch] OpenMP/Fortran: Reject declarations between target + teams (was: [Patch] OpenMP/Fortran: Reject not strictly nested target -> teams [PR110725, PR71065])

2023-07-25 Thread Tobias Burnus

On 24.07.23 21:49, Jakub Jelinek via Fortran wrote:

On Mon, Jul 24, 2023 at 09:43:10PM +0200, Tobias Burnus wrote:

This patch adds diagnostic for additional code alongside a nested teams
in a target region.

Thanks for working on this.  The fuzzy thing on the Fortran side is
if e.g. multiple nested BLOCK statements can appear sandwiched in between
target and teams (of course without declarations in them)


Talking about declarations, I realized that I missed to diagnose them;
the attached patch should handle them as well. (Except for 'omp nothing'
and 'omp error', which return ST_NONE.)

Comments, remarks, suggestions? If none or no changes are required,
I will later commit the attached follow-up patch.

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP/Fortran: Reject declarations between target + teams

While commit r14-2754-g2e31fe431b08b0302e1fa8a1c18ee51adafd41df
detected executable statements, declarations do not show up as
executable statements.  Hence, we now check whether the first
statement after TARGET is TEAMS - such that we can detect data
statements like type or variable declarations.  Fortran semantics
ensures that only executable directives/statemens can come after
'!$omp end teams' such that those can be detected with the
previous check.

Note that statements returning ST_NONE such as 'omp nothing' or
'omp error at(compilation)' will still slip through.

	PR fortran/110725
	PR middle-end/71065

gcc/fortran/ChangeLog:

	* gfortran.h (gfc_omp_clauses): Add target_first_st_is_teams.
	* parse.cc (parse_omp_structured_block): Set it if the first
	statement in the structured block of a TARGET is TEAMS or
	a combined/composite starting with TEAMS.
	* openmp.cc (resolve_omp_target): Also show an error for
	contains_teams_construct without target_first_st_is_teams.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/teams-6.f90: New test.

 gcc/fortran/gfortran.h |  2 +-
 gcc/fortran/openmp.cc  | 13 ++---
 gcc/fortran/parse.cc   | 25 --
 gcc/testsuite/gfortran.dg/gomp/teams-6.f90 | 78 ++
 4 files changed, 108 insertions(+), 10 deletions(-)

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 577ef807af7..9a00e6dea6f 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1575,7 +1575,7 @@ typedef struct gfc_omp_clauses
   unsigned order_unconstrained:1, order_reproducible:1, capture:1;
   unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak:1;
   unsigned non_rectangular:1, order_concurrent:1;
-  unsigned contains_teams_construct:1;
+  unsigned contains_teams_construct:1, target_first_st_is_teams:1;
   ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
   ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
   ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 675011a18ce..52eeaf2d4da 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -10666,12 +10666,13 @@ resolve_omp_target (gfc_code *code)
 
   if (!code->ext.omp_clauses->contains_teams_construct)
 return;
-  if ((GFC_IS_TEAMS_CONSTRUCT (code->block->next->op)
-   && code->block->next->next == NULL)
-  || (code->block->next->op == EXEC_BLOCK
-	  && code->block->next->next
-	  && GFC_IS_TEAMS_CONSTRUCT (code->block->next->next->op)
-	  && code->block->next->next->next == NULL))
+  if (code->ext.omp_clauses->target_first_st_is_teams
+  && ((GFC_IS_TEAMS_CONSTRUCT (code->block->next->op)
+	   && code->block->next->next == NULL)
+	  || (code->block->next->op == EXEC_BLOCK
+	  && code->block->next->next
+	  && GFC_IS_TEAMS_CONSTRUCT (code->block->next->next->op)
+	  && code->block->next->next->next == NULL)))
 return;
   gfc_code *c = code->block->next;
   while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 011a39c3d04..aa6bb663def 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -5766,7 +5766,7 @@ parse_openmp_allocate_block (gfc_statement omp_st)
 static gfc_statement
 parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
 {
-  gfc_statement st, omp_end_st;
+  gfc_statement st, omp_end_st, first_st;
   gfc_code *cp, *np;
   gfc_state_data s;
 
@@ -5857,7 +5857,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
   gfc_namespace *my_ns = NULL;
   gfc_namespace *my_parent = NULL;
 
-  st = next_statement ();
+  first_st = st = next_statement ();
 
   if 

Re: [Patch] OpenMP/Fortran: Reject not strictly nested target -> teams [PR110725, PR71065]

2023-07-25 Thread Tobias Burnus

Now committed as r14-2754-g2e31fe431b08b0 with a minor addition:

On 24.07.23 22:05, Tobias Burnus wrote:

The current patch rejects nested blocks, be it 'omp target; block;
block; omp teams;'

which was before in the testcase. But now also

or be it 'omp target; block; block;end block; omp teams'.

is tested for.

Somehow, the second dg-error line in an modified testcase did not make
it in the first commit; now fixed in r14-2759-g50656980497d77

Tobias.
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 50656980497d77ac12a5e7179013a6af09ba32f7
Author: Tobias Burnus 
Date:   Tue Jul 25 09:28:43 2023 +0200

gfortran.dg/gomp/pr99226.f90: Add missing dg-error

Follow up to r14-2754-g2e31fe431b08b0302e1fa8a1c18ee51adafd41df
which added a check that a target region with teams does not
have anything anything else strictly nested in the target.

When changing the dg-error for this PR, somehow the addition of a
dg-error in a second line was lost (the message uses (1) and (2) as
location, showing two lines, both need a dg-error with the same message).

gcc/testsuite/ChangeLog:

* gfortran.dg/gomp/pr99226.f90: Update dg-error.
---
 gcc/testsuite/gfortran.dg/gomp/pr99226.f90 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99226.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99226.f90
index 2aea0c15585..d1b35076dd0 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99226.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99226.f90
@@ -3,7 +3,7 @@
 subroutine sub (n)
integer :: n, i
!$omp target	! { dg-error "OMP TARGET region at .1. with a nested TEAMS at .2. may not contain any other statement, declaration or directive outside of the single TEAMS construct" }
-   !$omp teams distribute dist_schedule (static,n+4)
+   !$omp teams distribute dist_schedule (static,n+4)	! { dg-error "OMP TARGET region at .1. with a nested TEAMS at .2. may not contain any other statement, declaration or directive outside of the single TEAMS construct" }
do i = 1, 8
end do
!$omp teams distribute dist_schedule (static,n+4)
commit 2e31fe431b08b0302e1fa8a1c18ee51adafd41df
Author: Tobias Burnus 
Date:   Mon Jul 24 22:57:07 2023 +0200

OpenMP/Fortran: Reject not strictly nested target -> teams [PR110725, PR71065]

OpenMP requires: "If a teams region is nested inside a target region, the
corresponding target construct must not contain any statements, declarations
or directives outside of the corresponding teams construct."

This commit checks now for this restriction.

PR fortran/110725
PR middle-end/71065

gcc/fortran/ChangeLog:

* gfortran.h (gfc_omp_clauses): Add contains_teams_construct.
* openmp.cc (resolve_omp_target): New; check for teams nesting.
(gfc_resolve_omp_directive): Call it.
* parse.cc (decode_omp_directive): Set contains_teams_construct
on enclosing ST_OMP_TARGET.

gcc/testsuite/ChangeLog:

* gfortran.dg/gomp/pr99226.f90: Update dg-error.
* gfortran.dg/gomp/teams-5.f90: New test.
---
 gcc/fortran/gfortran.h |   1 +
 gcc/fortran/openmp.cc  |  39 +++-
 gcc/fortran/parse.cc   |  33 +++
 gcc/testsuite/gfortran.dg/gomp/pr99226.f90 |   2 +-
 gcc/testsuite/gfortran.dg/gomp/teams-5.f90 | 150 +
 5 files changed, 223 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 6482a885211..577ef807af7 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1575,6 +1575,7 @@ typedef struct gfc_omp_clauses
   unsigned order_unconstrained:1, order_reproducible:1, capture:1;
   unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak:1;
   unsigned non_rectangular:1, order_concurrent:1;
+  unsigned contains_teams_construct:1;
   ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
   ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
   ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 05a697da071..675011a18ce 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -10653,6 +10653,41 @@ gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
 }
 
 
+static void
+resolve_omp_target (gfc_code *code)
+{
+#define GFC_IS_TEAMS_CONSTRUCT(op)			\
+  (op == EXEC_OMP_TEAMS	\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE			\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD		\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO	\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD	\
+   || op == EX

Re: [Patch] OpenMP/Fortran: Reject not strictly nested target -> teams [PR110725, PR71065]

2023-07-24 Thread Tobias Burnus

On 24.07.23 21:49, Jakub Jelinek via Fortran wrote:

Thanks for working on this.  The fuzzy thing on the Fortran side is
if e.g. multiple nested BLOCK statements can appear sandwiched in between
target and teams (of course without declarations in them), or if e.g.


The current patch rejects nested blocks, be it 'omp target; block;
block; omp teams;' or be it 'omp target; block; block;end block; omp teams'.

The current wording in the spec is also rather explicit as 'block' is a
statement.

(BTW: For 'block; block; omp teams', the simplistic search won't work
such that for those only the location of TARGET and not of TEAMS is
shown. I could try harder but as it is useful as is and such code should
be rare, I don't do it.)

Thus, I believe the patch should be fine.

Tobias

PS: I know that some regard {{{ }}} and block; block, ... end block; ...
as something to be ignored. Thus, for 'omp atomic', TR12 will allow any
number of curly braces and BLOCK/ENDBLOCK pairs. The wording there is
rather explicit but also localized, i.e. it won't affect other code
locations (for now at least).

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[Patch] OpenMP/Fortran: Reject not strictly nested target -> teams [PR110725, PR71065]

2023-07-24 Thread Tobias Burnus

This patch adds diagnostic for additional code alongside a nested teams
in a target region.

The diagnostic is happening soon after parsing such that expressions
in clauses are not yet expanded - those would end up before TEAMS
and can be very complicated (e.g. assume an allocatable-returning function).

(The patch diagnoses it in openmp.cc; after trans-openmp.cc it would
already be to late.)

Comments, remarks, suggestions?

Tobias

PS: Something similar is also needed for C/C++ but there templates
and lambda functions might make it harder to implement. In any case,
it has to be done in the FE. Tracked at PR71065
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP/Fortran: Reject not strictly nested target -> teams [PR110725, PR71065]

OpenMP requires: "If a teams region is nested inside a target region, the
corresponding target construct must not contain any statements, declarations
or directives outside of the corresponding teams construct."

Test for it!

	PR fortran/110725
	PR middle-end/71065

gcc/fortran/ChangeLog:

	* gfortran.h (gfc_omp_clauses): Add contains_teams_construct.
	* openmp.cc (resolve_omp_target): New; check for teams nesting.
	(gfc_resolve_omp_directive): Call it.
	* parse.cc (decode_omp_directive): Set contains_teams_construct
	on enclosing ST_OMP_TARGET.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/pr99226.f90: Update dg-error.
	* gfortran.dg/gomp/teams-5.f90: New test.

 gcc/fortran/gfortran.h |   1 +
 gcc/fortran/openmp.cc  |  39 -
 gcc/fortran/parse.cc   |  33 
 gcc/testsuite/gfortran.dg/gomp/pr99226.f90 |   2 +-
 gcc/testsuite/gfortran.dg/gomp/teams-5.f90 | 127 +
 5 files changed, 200 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 6482a885211..577ef807af7 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1575,6 +1575,7 @@ typedef struct gfc_omp_clauses
   unsigned order_unconstrained:1, order_reproducible:1, capture:1;
   unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak:1;
   unsigned non_rectangular:1, order_concurrent:1;
+  unsigned contains_teams_construct:1;
   ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
   ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
   ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 05a697da071..675011a18ce 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -10653,6 +10653,41 @@ gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
 }
 
 
+static void
+resolve_omp_target (gfc_code *code)
+{
+#define GFC_IS_TEAMS_CONSTRUCT(op)			\
+  (op == EXEC_OMP_TEAMS	\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE			\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD		\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO	\
+   || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD	\
+   || op == EXEC_OMP_TEAMS_LOOP)
+
+  if (!code->ext.omp_clauses->contains_teams_construct)
+return;
+  if ((GFC_IS_TEAMS_CONSTRUCT (code->block->next->op)
+   && code->block->next->next == NULL)
+  || (code->block->next->op == EXEC_BLOCK
+	  && code->block->next->next
+	  && GFC_IS_TEAMS_CONSTRUCT (code->block->next->next->op)
+	  && code->block->next->next->next == NULL))
+return;
+  gfc_code *c = code->block->next;
+  while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
+c = c->next;
+  if (c)
+gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
+	   "contain any other statement, declaration or directive outside "
+	   "of the single TEAMS construct", >loc, >loc);
+  else
+gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
+	   "contain any other statement, declaration or directive outside "
+	   "of the single TEAMS construct", >loc);
+#undef GFC_IS_TEAMS_CONSTRUCT
+}
+
+
 /* Resolve OpenMP directive clauses and check various requirements
of each directive.  */
 
@@ -10703,6 +10738,9 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
 case EXEC_OMP_TEAMS_LOOP:
   resolve_omp_do (code);
   break;
+case EXEC_OMP_TARGET:
+  resolve_omp_target (code);
+  gcc_fallthrough ();
 case EXEC_OMP_ALLOCATE:
 case EXEC_OMP_ALLOCATORS:
 case EXEC_OMP_ASSUME:
@@ -10718,7 +10756,6 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
 case EXEC_OMP_SCOPE:
 case EXEC_OMP_SECTIONS:
 case EXEC_OMP_SINGLE:
-case EXEC_OMP_TARGET:
 case EXEC_OMP_TARGET_DATA:
 case EXEC_OMP_TARGET_ENTER_DATA:
 case EXEC_OMP_TARGET_EXIT_DATA:
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index e53b7a42e92..011a39c3d04 100644
--- 

[committed] - Re: [patch] OpenMP/Fortran: Non-rectangular loops with constant steps other than 1 or -1 [PR107424]

2023-07-19 Thread Tobias Burnus

Now committed as Rev. r14-2634-g85da0b40538fb0

Changes:

* I missed to updated another 'sorry' (msg wording change) - now fixed;
I also added it to the sorry-testcase file non-rectangular-loop-5.f90.

* I decided to retire the PR as several issues have been fixed and the
original title did not fit any more. The remaining issue is now tracked
in PR110735 (i.e. handling step != const, both the generic and possibly
a simpler special case).

* I added a link to the PR to libgomp.texi such that one can find out
what is only partially supported for Fortran.

Thanks,

Tobias

PS: Otherwise, the following still applies:

On 18.07.23 14:11, Tobias Burnus wrote:

Comments regarding the validity of the Fortran assumptions are welcome!

This patch now uses a 'simple' loop for OpenMP loops with
a constant loop-step size. Before, it only did so for step = ±1.
(Otherwise, a count variable is used from which the original
loop index variable is calculated from.)

For details, see the attached patch or
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107424#c12
(comment 12 + 14 plus the email linked in comment 12).

Comments? Remarks? If there are none, I will relatively soonish
commit the attached patch to mainline, only.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 85da0b40538fb0d17d89de1e7905984668e3dfef
Author: Tobias Burnus 
Date:   Wed Jul 19 10:18:49 2023 +0200

OpenMP/Fortran: Non-rectangular loops with constant steps other than 1 or -1 [PR107424]

Before this commit, gfortran produced with OpenMP for 'do i = 1,10,2'
the code
  for (count.0 = 0; count.0 < 5; count.0 = count.0 + 1)
i = count.0 * 2 + 1;

While such an inner loop can be collapsed, a non-rectangular could not.
With this commit and for all constant loop steps, a simple loop such
as 'for (i = 1; i <= 10; i = i + 2)' is created. (Before only for the
constant steps of 1 and -1.)

The constant step permits to know the direction (increasing/decreasing)
that is required for the loop condition.

The new code is only valid if one assumes no overflow of the loop variable.
However, the Fortran standard can be read that this must be ensured by
the user. Namely, the Fortran standard requires (F2023, 10.1.5.2.4):
"The execution of any numeric operation whose result is not defined by
the arithmetic used by the processor is prohibited."

And, for DO loops, F2023's "11.1.7.4.3 The execution cycle" has the
following: The number of loop iterations handled by an iteration count,
which would permit code like 'do i = huge(i)-5, huge(i),4'. However,
in step (3), this count is not only decremented by one but also:
  "... The DO variable, if any, is incremented by the value of the
  incrementation parameter m3."
And for the example above, 'i' would be 'huge(i)+3' in the last
execution cycle, which exceeds the largest model number and should
render the example as invalid.

PR fortran/107424

gcc/fortran/ChangeLog:

* trans-openmp.cc (gfc_nonrect_loop_expr): Accept all
constant loop steps.
(gfc_trans_omp_do): Likewise; use sign to determine
loop direction.

libgomp/ChangeLog:

* libgomp.texi (Impl. Status 5.0): Add link to new PR110735.
* testsuite/libgomp.fortran/non-rectangular-loop-1.f90: Enable
commented tests.
* testsuite/libgomp.fortran/non-rectangular-loop-1a.f90: Remove
test file; tests are in non-rectangular-loop-1.f90.
* testsuite/libgomp.fortran/non-rectangular-loop-5.f90: Change
testcase to use a non-constant step to retain the 'sorry' test.
* testsuite/libgomp.fortran/non-rectangular-loop-6.f90: New test.

gcc/testsuite/ChangeLog:

* gfortran.dg/gomp/linear-2.f90: Update dump to remove
the additional count variable.
---
 gcc/fortran/trans-openmp.cc|  18 +-
 gcc/testsuite/gfortran.dg/gomp/linear-2.f90|   4 +-
 libgomp/libgomp.texi   |   4 +-
 .../libgomp.fortran/non-rectangular-loop-1.f90 | 537 ++---
 .../libgomp.fortran/non-rectangular-loop-1a.f90| 374 --
 .../libgomp.fortran/non-rectangular-loop-5.f90 |  22 +-
 .../libgomp.fortran/non-rectangular-loop-6.f90 | 196 
 7 files changed, 494 insertions(+), 661 deletions(-)

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index c88ee3c7656..cf741cebf91 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5374,10 +5374,10 @@ gfc_nonrect_loop_expr (stmtbloc

[patch] OpenMP/Fortran: Non-rectangular loops with constant steps other than 1 or -1 [PR107424]

2023-07-18 Thread Tobias Burnus

Comments regarding the validity of the Fortran assumptions are welcome!

This patch now uses a 'simple' loop for OpenMP loops with
a constant loop-step size. Before, it only did so for step = ±1.
(Otherwise, a count variable is used from which the original
loop index variable is calculated from.)

For details, see the attached patch or
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107424#c12
(comment 12 + 14 plus the email linked in comment 12).

Comments? Remarks? If there are none, I will relatively soonish
commit the attached patch to mainline, only.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP/Fortran: Non-rectangular loops with constant steps other than 1 or -1 [PR107424]

Before this commit, gfortran produced with OpenMP for 'do i = 1,10,2'
the code
  for (count.0 = 0; count.0 < 5; count.0 = count.0 + 1)
i = count.0 * 2 + 1;

While such an inner loop can be collapsed, a non-rectangular could not.
With this commit and for all constant loop steps, a simple loop such
as 'for (i = 1; i <= 10; i = i + 2)' is created. (Before only for the
constant steps of 1 and -1.)

The constant step permits to know the direction (increasing/decreasing)
that is required for the loop condition.

The new code is only valid if one assumes no overflow of the loop variable.
However, the Fortran standard can be read that this must be ensured by
the user. Namely, the Fortran standard requires (F2023, 10.1.5.2.4):
"The execution of any numeric operation whose result is not defined by
the arithmetic used by the processor is prohibited."

And, for DO loops, F2023's "11.1.7.4.3 The execution cycle" has the
following: The number of loop iterations handled by an iteration count,
which would permit code like 'do i = huge(i)-5, huge(i),4'. However,
in step (3), this count is not only decremented by one but also:
  "... The DO variable, if any, is incremented by the value of the
  incrementation parameter m3."
And for the example above, 'i' would be 'huge(i)+3' in the last
execution cycle, which exceeds the largest model number and should
render the example as invalid.

	PR fortran/107424

gcc/fortran/ChangeLog:

	* trans-openmp.cc (gfc_nonrect_loop_expr): Accept all
	constant loop steps.
	(gfc_trans_omp_do): Likewise; use sign to determine
	loop direction.

libgomp/ChangeLog:

	* testsuite/libgomp.fortran/non-rectangular-loop-1.f90: Enabled
	commented tests.
	* testsuite/libgomp.fortran/non-rectangular-loop-1a.f90: Removed.
	* testsuite/libgomp.fortran/non-rectangular-loop-5.f90: Change
	testcase to use a non-constant step to retain the 'sorry' test.
* testsuite/libgomp.fortran/non-rectangular-loop-6.f90: New test.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/linear-2.f90: Update dump to remove
	the additional count variable.

 gcc/fortran/trans-openmp.cc|  12 +-
 gcc/testsuite/gfortran.dg/gomp/linear-2.f90|   4 +-
 .../libgomp.fortran/non-rectangular-loop-1.f90 | 537 ++---
 .../libgomp.fortran/non-rectangular-loop-1a.f90| 374 --
 .../libgomp.fortran/non-rectangular-loop-5.f90 |  10 +-
 .../libgomp.fortran/non-rectangular-loop-6.f90 | 196 
 6 files changed, 477 insertions(+), 656 deletions(-)

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index c88ee3c7656..e33b18fdada 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5374,10 +5374,10 @@ gfc_nonrect_loop_expr (stmtblock_t *pblock, gfc_se *sep, int loop_n,
 
   if (!simple)
 {
-  /* FIXME: Handle non-unit iter steps, cf. PR fortran/107424.  */
+  /* FIXME: Handle non-const iter steps, cf. PR fortran/107424.  */
   sorry_at (gfc_get_location (_loop_var->where),
-		"non-rectangular loop nest with step other than constant 1 "
-		"or -1 for %qs", curr_loop_var->symtree->n.sym->name);
+		"non-rectangular loop nest with non-constant step for %qs",
+		curr_loop_var->symtree->n.sym->name);
   return false;
 }
 
@@ -5578,10 +5578,8 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
   gfc_add_block_to_block (pblock, );
   step = gfc_evaluate_now (se.expr, pblock);
 
-  if (integer_onep (step))
-	simple = 1;
-  else if (tree_int_cst_equal (step, integer_minus_one_node))
-	simple = -1;
+  if (TREE_CODE (step) == INTEGER_CST)
+	simple = tree_int_cst_sgn (step);
 
   gfc_init_se (, NULL);
   if (!clauses->non_rectangular
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-2.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-2.f90
index 05f007fd5c2..88df96e9b8f 100644
--- a/gcc/testsuite/gfortran.dg/gomp/linear-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-2.f90
@@ -105,8 +105,8 @@ end module
 ! { dg-final { scan-tree-dump-times "#pragma omp for 

[committed] OpenMP/Fortran: Parsing support for 'uses_allocators'

2023-07-17 Thread Tobias Burnus

Committed the attached patch as r14-2582-g89d0f082b3c95f.

This is about OpenMP's uses_allocators clause to the 'target' directive.

Using the clause with predefined allocators as list arguments is
required if those allocators are used in a target region - unless
there is an 'omp requires dynamic_allocators' in the compilation unit.

While the later is a no op (requirement fulfilled by all devices), we
still had to handle the no op when using 'uses_allocators', which this
commit does.

However, uses_allocators also permits to define new allocators; for
those, this commit stops after parsing and resolving with a
'sorry, unimplemented'.

Support for the latter will be added together with the C/C++ support
by a re-diffed/updated version of Chung-Lin's patch at
https://gcc.gnu.org/pipermail/gcc-patches/2022-June/596587.html

(See thread for pending review issues; the C++ member var issue
is https://gcc.gnu.org/PR110347 )

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 89d0f082b3c95f68d116d4480126e3ab7fb7f36b
Author: Tobias Burnus 
Date:   Mon Jul 17 15:13:44 2023 +0200

OpenMP/Fortran: Parsing support for 'uses_allocators'

The 'uses_allocators' clause to the 'target' construct accepts predefined
allocators and can also be used to define a new allocator for a target region.
As predefined allocators in GCC do not require special handling, those can and
are ignored after parsing, such that this feature now works. On the other hand,
defining a new allocator will fail for now with a 'sorry, unimplemented'.

Note that both the OpenMP 5.0/5.1 and 5.2 syntax for uses_allocators
is supported by this commit.

2023-07-17  Tobias Burnus  
Chung-Lin Tang  

gcc/fortran/ChangeLog:

* dump-parse-tree.cc (show_omp_namelist, show_omp_clauses): Dump
uses_allocators clause.
* gfortran.h (gfc_free_omp_namelist): Add memspace_sym to u union
and traits_sym to u2 union.
(OMP_LIST_USES_ALLOCATORS): New enum value.
(gfc_free_omp_namelist): Add 'bool free_mem_traits_space' arg.
* match.cc (gfc_free_omp_namelist): Likewise.
* openmp.cc (gfc_free_omp_clauses, gfc_match_omp_variable_list,
gfc_match_omp_to_link, gfc_match_omp_doacross_sink,
gfc_match_omp_clause_reduction, gfc_match_omp_allocate,
gfc_match_omp_flush): Update call.
(gfc_match_omp_clauses): Likewise. Parse uses_allocators clause.
(gfc_match_omp_clause_uses_allocators): New.
(enum omp_mask2): Add new OMP_CLAUSE_USES_ALLOCATORS.
(OMP_TARGET_CLAUSES): Accept it.
(resolve_omp_clauses): Resolve uses_allocators clause
* st.cc (gfc_free_statement): Update gfc_free_omp_namelist call.
* trans-openmp.cc (gfc_trans_omp_clauses): Handle
OMP_LIST_USES_ALLOCATORS; fail with sorry unless predefined allocator.
(gfc_split_omp_clauses): Handle uses_allocators.

libgomp/ChangeLog:

* testsuite/libgomp.fortran/uses_allocators_1.f90: New test.
* testsuite/libgomp.fortran/uses_allocators_2.f90: New test.

Co-authored-by: Chung-Lin Tang 
---
 gcc/fortran/dump-parse-tree.cc |  24 +++
 gcc/fortran/gfortran.h |   5 +-
 gcc/fortran/match.cc   |   7 +-
 gcc/fortran/openmp.cc  | 194 +++--
 gcc/fortran/st.cc  |   2 +-
 gcc/fortran/trans-openmp.cc|  11 ++
 .../libgomp.fortran/uses_allocators_1.f90  | 168 ++
 .../libgomp.fortran/uses_allocators_2.f90  |  99 +++
 8 files changed, 491 insertions(+), 19 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index effcebe9325..68122e3e6fd 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -1497,6 +1497,29 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n)
 	  case OMP_LINEAR_UVAL: fputs ("uval(", dumpfile); break;
 	  default: break;
 	  }
+  else if (list_type == OMP_LIST_USES_ALLOCATORS)
+	{
+	  if (n->u.memspace_sym)
+	{
+	  fputs ("memspace(", dumpfile);
+	  fputs (n->sym->name, dumpfile);
+	  fputc (')', dumpfile);
+	}
+	  if (n->u.memspace_sym && n->u2.traits_sym)
+	fputc (',', dumpfile);
+	  if (n->u2.traits_sym)
+	{
+	  fputs ("traits(", dumpfile);
+	  fputs (n->u2.traits_sym->name, dumpfile);
+	  fputc (')', dumpfile);
+	}
+	  if (n->u.memspace_sym || n->u2.traits

Re: [Patch, fortran] PR108961 - Segfault when associating to pointer from C_F_POINTER

2023-06-20 Thread Tobias Burnus

On 20.06.23 18:19, Paul Richard Thomas via Fortran wrote:


Is there a better way to detect a type(c_ptr) formal argument?

u.derived->intmod_sym_id == ISOCBINDING_PTR ?

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[committed] Fortran: Fix parse-dump-tree for OpenMP ALLOCATE clause

2023-06-20 Thread Tobias Burnus

A rather obvious fix. The allocator(...) bit showed up with -fdump-parse-tree.

Committed as Rev. r14-1988-g99e3214f582b08

Side remark:

Regarding the example inside the commit log: OpenMP 5.1 permitted derived-type
components. Due to global wording changes, OpenMP 5.2 disabled it for both
the new 'allocators' and for the old 'allocate' directive. This turned out to be
an accidental change and it will be permitted in a future OpenMP version again
(for 'allocators' as the executable form of the 'allocate' directive was 
deprecated
and then removed; in GCC, we will have to support it for both for legacy support
reasons). – While n->expr is now support for the dump, it is currently 
unreachable
as dt-component parsing is disabled for both allocate and allocators. (To be 
changed.)

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 99e3214f582b08b69b11b53eb3fc73b0919ef4f1
Author: Tobias Burnus 
Date:   Tue Jun 20 13:46:11 2023 +0200

Fortran: Fix parse-dump-tree for OpenMP ALLOCATE clause

Commit r14-1301-gd64e8e1224708e added u2.allocator to gfc_omp_namelist
for better readability and to permit to use namelist->expr for code
like the following:
  !$omp allocators allocate(align(32) : dt%alloc_comp)
allocate (dt%alloc_comp(5))
  !$omp allocate(dt%alloc_comp2) align(64)
allocate (dt%alloc_comp2(10))
However, for the parse-tree dump the change was incomplete.

gcc/fortran/ChangeLog:

* dump-parse-tree.cc (show_omp_namelist): Fix dump of the allocator
modifier of OMP_LIST_ALLOCATE.

diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 99c8bdaadce..effcebe9325 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -1370,31 +1370,34 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n)
 		  fputc (list_type == OMP_LIST_AFFINITY ? ':' : ',', dumpfile);
 		}
 	}
 	  ns_iter = n->u2.ns;
 	}
   if (list_type == OMP_LIST_ALLOCATE)
 	{
-	  if (n->expr)
+	  if (n->u2.allocator)
 	{
 	  fputs ("allocator(", dumpfile);
 	  show_expr (n->u2.allocator);
 	  fputc (')', dumpfile);
 	}
 	  if (n->expr && n->u.align)
 	fputc (',', dumpfile);
 	  if (n->u.align)
 	{
 	  fputs ("align(", dumpfile);
 	  show_expr (n->u.align);
 	  fputc (')', dumpfile);
 	}
-	  if (n->expr || n->u.align)
+	  if (n->u2.allocator || n->u.align)
 	fputc (':', dumpfile);
-	  fputs (n->sym->name, dumpfile);
+	  if (n->expr)
+	show_expr (n->expr);
+	  else
+	fputs (n->sym->name, dumpfile);
 	  if (n->next)
 	fputs (") ALLOCATE(", dumpfile);
 	  continue;
 	}
   if (list_type == OMP_LIST_REDUCTION)
 	switch (n->u.reduction_op)
 	  {


[Patch] Fortran's gfc_match_char: %S to match symbol with host_assoc

2023-06-20 Thread Tobias Burnus

When just matching a symbol, one can use 'gfc_match_symbol (, host_assoc)'
and has the option to match with and without host association.

However, when matching something more complex via 'gfc_match' like
"something ( %s ) , " the match uses host_assoc = false.
While it can be combined ("something (" + symbol + " ) ,"), this requires
keeping track of the previous location and resetting it.

It seems to be much simply to add a new flag supporting host_assoc = true,
which this patch does (using '%S'). The advantage is also that when looking
at the comment or at the "%s" implementation, it is clear that there are two
variants, making it less likely to choose the wrong matching.

OK for mainline?

Tobias

PS: I will use it in an upcoming OpenMP to parse 'uses_allocators'.
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
Fortran's gfc_match_char: %S to match symbol with host_assoc

gfc_match ("... %s ...", ...) matches a gfc_symbol but with
host_assoc = 0. This commit adds '%S' as variant which matches
with host_assoc = 1

gcc/fortran/ChangeLog:

	* match.cc (gfc_match_char): Match with '%S' a symbol
	with host_assoc = 1.

diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc
index e7be7fddc64..a350ebf754e 100644
--- a/gcc/fortran/match.cc
+++ b/gcc/fortran/match.cc
@@ -1084,7 +1084,8 @@ gfc_match_char (char c, bool gobble_ws)
 
%%  Literal percent sign
%e  Expression, pointer to a pointer is set
-   %s  Symbol, pointer to the symbol is set
+   %s  Symbol, pointer to the symbol is set (host_assoc = 0)
+   %S  Symbol, pointer to the symbol is set (host_assoc = 1)
%n  Name, character buffer is set to name
%t  Matches end of statement.
%o  Matches an intrinsic operator, returned as an INTRINSIC enum.
@@ -1151,8 +1152,9 @@ loop:
 	  goto loop;
 
 	case 's':
+	case 'S':
 	  vp = va_arg (argp, void **);
-	  n = gfc_match_symbol ((gfc_symbol **) vp, 0);
+	  n = gfc_match_symbol ((gfc_symbol **) vp, c == 'S');
 	  if (n != MATCH_YES)
 	{
 	  m = n;



[committed] Doc update: -foffload-options= examples + OpenMP in Fortran intrinsic modules

2023-06-19 Thread Tobias Burnus

Since r14-1807-g4bcb46b3ade179, using -foffload-options='-lgfortran -lm' are
no longer required as they get automatically linked on the offload side, if
linked on the host side. (Linking with g++ implies -lm, with gfortran
'-lgfortran -lm', while an explicit 'gcc -lm -lgfortran' would also do the
autolinking.) [Note: This only affects those two libraries.]

As there the number of useful flags reduced, new ones were added, including
-foffload-options=-O3. While possible, I believe that flag is misleading as
it implies that no optimization is done unless an -O... flag has been passed
to the run-time library.

But like now for -lm and -lgfortran, also the -O... flags are automatically
passed on from the host flags. (While they can be overridden, this is usually
not required.) — As the previous line already shows an example, i.e.
  "-foffload-options='-fno-math-errno -ffinite-math-only'",
I think we can get rid of this line without needing to find another example.

* * *

Looking at Fortran's fortran/intrinsic.texi I saw references to 4.5 and 5.0;
I have now added 5.1 and 5.2 – hopefully, we can at replace them soon
(GCC 15?) the v4.5 to 5.2 by just 5.2, having implemented all of 5.x.

(The reference to v4.5 in GCC's and gfortran's invoke.texi feels also odd
as v5.* is supported and the attribute syntax shown for C/C++ is only in
v5.x. To be changed - but not now.)


Additionally, fortran/intrinsic.texi listed the content of the OMP_* modules
(except for the API routines) but missed two recently added named constants,
which I now added.

Committed as r14-1936-ge9c1679c350be0.

Like always, comments are highly welcome!

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit e9c1679c350be09cec5354a3d98915c3afe02c87
Author: Tobias Burnus 
Date:   Mon Jun 19 10:24:08 2023 +0200

Doc update: -foffload-options= examples + OpenMP in Fortran intrinsic modules

With LTO, the -O.. flags of the host are passed on to the lto compiler, which
also includes offloading compilers. Therefore, using --foffload-options=-O3 is
misleading as it implies that without the default optimizations are used. Hence,
this flags has now been removed from the usage examples.

The Fortran documentation lists the content (except for API routines) routines
of the intrinsic OpenMP modules OMP_LIB and OMP_LIB_KINDS; this commit adds
two missing named constants and links also to the OpenMP 5.1 and 5.2
OpenMP spec for completeness.

gcc/ChangeLog:

* doc/invoke.texi (-foffload-options): Remove '-O3' from the examples.

gcc/fortran/ChangeLog:

* intrinsic.texi (OpenMP Modules OMP_LIB and OMP_LIB_KINDS): Also
add references to the OpenMP 5.1 and 5.2 spec; add omp_initial_device
and omp_invalid_device named constants.
---
 gcc/doc/invoke.texi|  2 +-
 gcc/fortran/intrinsic.texi | 20 
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index fafdee30f66..215ab0dd05c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -2718,7 +2718,7 @@ Typical command lines are
 
 @smallexample
 -foffload-options='-fno-math-errno -ffinite-math-only' -foffload-options=nvptx-none=-latomic
--foffload-options=amdgcn-amdhsa=-march=gfx906 -foffload-options=-O3
+-foffload-options=amdgcn-amdhsa=-march=gfx906
 @end smallexample
 
 @opindex fopenacc
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index db227ea..6c7ad03a02c 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -15247,8 +15247,9 @@ with the following options: @code{-fno-unsafe-math-optimizations
 @table @asis
 @item @emph{Standard}:
 OpenMP Application Program Interface v4.5,
-OpenMP Application Program Interface v5.0 (partially supported) and
-OpenMP Application Program Interface v5.1 (partially supported).
+OpenMP Application Program Interface v5.0 (partially supported),
+OpenMP Application Program Interface v5.1 (partially supported) and
+OpenMP Application Program Interface v5.2 (partially supported).
 @end table
 
 The OpenMP Fortran runtime library routines are provided both in
@@ -15262,9 +15263,13 @@ below.
 
 For details refer to the actual
 @uref{https://www.openmp.org/wp-content/uploads/openmp-4.5.pdf,
-OpenMP Application Program Interface v4.5} and
+OpenMP Application Program Interface v4.5},
 @uref{https://www.openmp.org/wp-content/uploads/OpenMP-API-Specification-5.0.pdf,
-OpenMP Application Program Interface v5.0}.
+OpenMP Application Program Interface v5.0},
+@uref{https://www.openmp.org/wp-content/uploads/OpenMP-API-Specification-5-1.pdf,
+OpenMP Application Program Interface v5.1} and
+@uref{https://www.openmp.org/

Re: [ping] Add 'libgomp.{,oacc-}fortran/fortran-torture_execute_math.f90'

2023-06-13 Thread Tobias Burnus

On 13.06.23 12:42, Thomas Schwinge wrote:

On 2023-06-05T14:18:48+0200, I wrote:

OK to push the attached
"Add 'libgomp.{,oacc-}fortran/fortran-torture_execute_math.f90'"?


Subject: [PATCH] Add
  'libgomp.{,oacc-}fortran/fortran-torture_execute_math.f90'

  gcc/testsuite/
  * gfortran.fortran-torture/execute/math.f90: Enhance for optional
  OpenACC, OpenMP 'target' usage.


I think it is more readable with a linebreak here and with "OpenACC
'serial' and OpenMP ..." instead of "OpenACC, OpenMP".

What I would like to see a hint somewhere in the commit log that the
libgomp files include the gfortran.fortran-torture file. I don't care
whether you add the hint before the changelog items as free text – or in
the bullet above (e.g. "as it is included in libgomp/testsuite") – or
after "New." in the following bullet list.


  libgomp/
  * testsuite/libgomp.fortran/fortran-torture_execute_math.f90: New.
  * testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90:
  Likewise.



---
  .../gfortran.fortran-torture/execute/math.f90 | 23 +--
  .../fortran-torture_execute_math.f90  |  4 
  .../fortran-torture_execute_math.f90  |  5 
  3 files changed, 30 insertions(+), 2 deletions(-)
  create mode 100644 
libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90
  create mode 100644 
libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90

diff --git a/gcc/testsuite/gfortran.fortran-torture/execute/math.f90 
b/gcc/testsuite/gfortran.fortran-torture/execute/math.f90
index 17cc78f7a10..e71f669304f 100644
--- a/gcc/testsuite/gfortran.fortran-torture/execute/math.f90
+++ b/gcc/testsuite/gfortran.fortran-torture/execute/math.f90
@@ -1,9 +1,14 @@
  ! Program to test mathematical intrinsics
+
+! See also 
'libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90'; thus the 
'!$omp' directives.
+! See also 
'libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90'; thus 
the '!$acc' directives.


Likewise here: it is not completely obvious that this file is 'include'd
by the other testcases.

Maybe add a line "! This file is also included in:" and remove the "See
also" or some creative variant of it.

Minor remark: The OpenMP part is OK, but strict reading of the spec
requires an "omp declare target' if a subroutine is in a different
compilation unit. And according the glossary, that's the case here. In
practice, it also works without as it is in the same translation unit.
(compilation unit = for C/C++: translation unit, for Fortran:
subprogram). I think the HPE/Cray compiler will complain, but maybe only
when used with modules and not with subroutine subprograms. (As many
compilers write a .mod file for modules, a late change of attributes can
be more problematic.)

Otherwise LGTM.

Tobias

PS: I assume that you have check it with both with an in-build-tree and
an in-install-tree testsuite run.


+
  subroutine dotest (n, val4, val8, known)
 implicit none
 real(kind=4) val4, known
 real(kind=8) val8
 integer n
+   !$acc routine seq

 if (abs (val4 - known) .gt. 0.001) STOP 1
 if (abs (real (val8, kind=4) - known) .gt. 0.001) STOP 2
@@ -14,17 +19,20 @@ subroutine dotestc (n, val4, val8, known)
 complex(kind=4) val4, known
 complex(kind=8) val8
 integer n
+   !$acc routine seq
+
 if (abs (val4 - known) .gt. 0.001) STOP 3
 if (abs (cmplx (val8, kind=4) - known) .gt. 0.001) STOP 4
  end subroutine

-program testmath
+subroutine testmath
 implicit none
 real(kind=4) r, two4, half4
 real(kind=8) q, two8, half8
 complex(kind=4) cr
 complex(kind=8) cq
 external dotest, dotestc
+   !$acc routine seq

 two4 = 2.0
 two8 = 2.0_8
@@ -96,5 +104,16 @@ program testmath
 cq = log ((-1.0_8, -1.0_8))
 call dotestc (21, cr, cq, (0.3466, -2.3562))

-end program
+end subroutine

+program main
+   implicit none
+   external testmath
+
+   !$acc serial
+   !$omp target
+   call testmath
+   !$acc end serial
+   !$omp end target
+
+end program
diff --git a/libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90 
b/libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90
new file mode 100644
index 000..3348a0bb3ad
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90
@@ -0,0 +1,4 @@
+! { dg-do run }
+! { dg-additional-options -foffload-options=-lm }
+
+include '../../../gcc/testsuite/gfortran.fortran-torture/execute/math.f90'
diff --git 
a/libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90
new file mode 100644
index 000..1b2ac440762
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90
@@ -0,0 +1,5 @@
+! { dg-do run }
+!TODO { dg-prune-output {using 'vector_length \(32\)', ignoring 1} }
+! { dg-additional-options -foffload-options=-lm }
+

Fwd: GNU Tools Cauldron 2023

2023-06-05 Thread Tobias Burnus

FYI — in case you want to come to Cambridge in September. (I intent to
be there.) - Tobias

 Forwarded Message 
Subject:GNU Tools Cauldron 2023
Date:   Mon, 5 Jun 2023 14:59:05 +0100
From:   Richard Earnshaw
To: GCC Development



We are pleased to invite you all to the next GNU Tools Cauldron,
taking place in Cambridge, UK, on September 22-24, 2023.

As for the previous instances, we have setup a wiki page for
details:

https://gcc.gnu.org/wiki/cauldron2023>

Like last year, we are having to charge for attendance. We are still
working out what we will need to charge, but it will be no more than £250.

Attendance will remain free for community volunteers and others who do
not have a commercial backer and we will be providing a small number of
travel bursaries for students to attend.

For all details of how to register, and how to submit a proposal for a
track session, please see the wiki page.

The Cauldron is organized by a group of volunteers. We are keen to add
some more people so others can stand down. If you'd like to be part of
that organizing committee, please email the same address.

This announcement is being sent to the main mailing list of the
following groups: GCC, GDB, binutils, CGEN, DejaGnu, newlib and glibc.

Please feel free to share with other groups as appropriate.

Richard (on behalf of the GNU Tools Cauldron organizing committee).
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[Patch] OpenMP/Fortran: Permit pure directives inside PURE

2023-05-31 Thread Tobias Burnus

I intent to commit the attached patch soon.

However, I want to give anyone the chance to comment on any aspect before
committing. Comments after the commit are welcome as well :-)

OpenMP 5.2 now uses properties to clauses and "pure" is among those properties.

Note that pure-2.f90 contains also stubs for directives only added in TR11 or 
TR12
to reduce the chance of missing those once they get implemented.
Additionally, 'scan' is 'pure' only since very recently - which I read
as bug fix; hence, it is accepted with the attached patch.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP/Fortran: Permit pure directives inside PURE

Update permitted directives for directives marked in OpenMP's 5.2 as pure.
To ensure that list is updated, unimplemented directives are placed into
pure-2.f90 such the test FAILs once a known to be pure directive is
implemented without handling its pureness.

gcc/fortran/ChangeLog:

	* parse.cc (decode_omp_directive): Accept all pure directives
	inside a PURE procedures; handle 'error at(execution).

libgomp/ChangeLog:

	* libgomp.texi (OpenMP 5.2): Mark pure-directive handling as 'Y'.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/nothing-2.f90: Remove one dg-error.
	* gfortran.dg/gomp/pr79154-2.f90: Update expected dg-error wording.
	* gfortran.dg/gomp/pr79154-simd.f90: Likewise.
	* gfortran.dg/gomp/pure-1.f90: New test.
	* gfortran.dg/gomp/pure-2.f90: New test.
	* gfortran.dg/gomp/pure-3.f90: New test.
	* gfortran.dg/gomp/pure-4.f90: New test.

 gcc/fortran/parse.cc| 50 +-
 gcc/testsuite/gfortran.dg/gomp/nothing-2.f90|  2 +-
 gcc/testsuite/gfortran.dg/gomp/pr79154-2.f90| 24 +++
 gcc/testsuite/gfortran.dg/gomp/pr79154-simd.f90 |  2 +-
 gcc/testsuite/gfortran.dg/gomp/pure-1.f90   | 88 +
 gcc/testsuite/gfortran.dg/gomp/pure-2.f90   | 73 
 gcc/testsuite/gfortran.dg/gomp/pure-3.f90   | 31 +
 gcc/testsuite/gfortran.dg/gomp/pure-4.f90   | 35 ++
 libgomp/libgomp.texi|  2 +-
 9 files changed, 277 insertions(+), 30 deletions(-)

diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 9730ab095e2..733294c8cfa 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -934,7 +934,16 @@ decode_omp_directive (void)
  first (those also shall not turn off implicit pure).  */
   switch (c)
 {
+case 'a':
+  /* For -fopenmp-simd, ignore 'assumes'; note no clause starts with 's'. */
+  if (!flag_openmp && gfc_match ("assumes") == MATCH_YES)
+	break;
+  matcho ("assumes", gfc_match_omp_assumes, ST_OMP_ASSUMES);
+  matchs ("assume", gfc_match_omp_assume, ST_OMP_ASSUME);
+  break;
 case 'd':
+  matchds ("declare reduction", gfc_match_omp_declare_reduction,
+	   ST_OMP_DECLARE_REDUCTION);
   matchds ("declare simd", gfc_match_omp_declare_simd,
 	   ST_OMP_DECLARE_SIMD);
   matchdo ("declare target", gfc_match_omp_declare_target,
@@ -942,16 +951,25 @@ decode_omp_directive (void)
   matchdo ("declare variant", gfc_match_omp_declare_variant,
 	   ST_OMP_DECLARE_VARIANT);
   break;
+case 'e':
+  matchs ("end assume", gfc_match_omp_eos_error, ST_OMP_END_ASSUME);
+  matchs ("end simd", gfc_match_omp_eos_error, ST_OMP_END_SIMD);
+  matcho ("error", gfc_match_omp_error, ST_OMP_ERROR);
+  break;
 case 's':
+  matchs ("scan", gfc_match_omp_scan, ST_OMP_SCAN);
   matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
   break;
+case 'n':
+  matcho ("nothing", gfc_match_omp_nothing, ST_NONE);
+  break;
 }
 
   pure_ok = false;
   if (flag_openmp && gfc_pure (NULL))
 {
-  gfc_error_now ("OpenMP directives other than SIMD or DECLARE TARGET "
-		 "at %C may not appear in PURE procedures");
+  gfc_error_now ("OpenMP directive at %C is not pure and thus may not "
+		 "appear in a PURE procedure");
   gfc_error_recovery ();
   return ST_NONE;
 }
@@ -967,11 +985,6 @@ decode_omp_directive (void)
   else
 	matcho ("allocate", gfc_match_omp_allocate, ST_OMP_ALLOCATE);
   matcho ("allocators", gfc_match_omp_allocators, ST_OMP_ALLOCATORS);
-  /* For -fopenmp-simd, ignore 'assumes'; note no clause starts with 's'. */
-  if (!flag_openmp && gfc_match ("assumes") == MATCH_YES)
-	break;
-  matcho ("assumes", gfc_match_omp_assumes, ST_OMP_ASSUMES);
-  matchs ("assume", gfc_match_omp_assume, ST_OMP_ASSUME);
   matcho ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC);
   break;
 case 'b':
@@ -984,8 +997,6 @@ decode_omp_directive (void)
   matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
   break;
 case 'd':
-  matchds ("declare 

[committed][Patch] Fortran/OpenMP: Add parsing support for allocators/allocate directives

2023-05-26 Thread Tobias Burnus

I have now re-diffed the patch and cleaned up some comments, and spend
some time proof reading it myself. And have now committed it as
r14-1301-gd64e8e1224708e7f5b87c531aeb26f1ed07f91ff

As the subject line states, it adds parsing support for "!$omp allocate"
as declarative directive and (if preceded by an executable
statement/directive) as deprecated alias for '!$omp allocators', which
is also supported. — After successful checking, it fails with the usual
"sorry, not yet implemented".

Like always, comments and suggestions are welcome.

Tobias

PS: The real challenge will be to get 'allocators' working as gfortran
currently calls malloc/free/realloc directly and this will not work well
if memory is allocated differently, e.g., by omp_alloc and friends. But
that's a separate issue, unrelated this parsing + error-diagnostic patch.

Probably simpler, especially for stack variables, would be the support
for the declarative 'allocate' directive (in C/C++/Fortran. Except for
some C++ template-handling polishing, the parsing support is there, but
middle-end wiring is still required.)

PPS: I filed a PR regarding the handling of 'structure elements' with
allocators, https://gcc.gnu.org/PR109998

PPPS: I remarked before:

On 21.12.22 16:51, Tobias Burnus wrote:

On 14.12.22 11:47, Tobias Burnus wrote:


This patch adds parsing/argument-checking support for
  '!$omp allocators allocate([align(int),allocator(a) :] list)'


This follow-up patch additionally adds parsing support for both
declarative and allocate-stmt-associated '!$omp allocate' directives –
and replaces my previous patch.

OK for mainline?

 * * *

The code requires in line with OpenMP 5.1 that an executable statement
comes before an '!$omp allocate' that is associated with a Fortran
ALLOCATE stmt, which is diagnosed.

Note: There is a spec change/regression related to permitting structure
elements; while OpenMP 5.0/5.1 did permit them in the
allocate-stmt-associated "!$omp allocate", OpenMP 5.2 stopped doing –
and '!$omp allocators' never permitted it. — For allocate that's seems
to be the accidental result from "permitted unless stated otherwise" to
"rejected unless stated otherwise". For 'allocators', it is the result
of the original 'allocate' clause which should have been extended for
'allocators' - or should not.

In any case, that's tracked now in OpenMP's spec issue #3437.

Thoughts? – The code rejects var%comp and var(1)%comp etc. for now –
besides the unclear spec status, I admittedly did this also to make
checking easier (like for duplicated entries, entry same as in ALLOCATE
except for tailing array spec etc.).

 * * *

This patch replaced both my previous patch in this thread and also
Abid's patch


"[PATCH 1/5] [gfortran] Add parsing support for allocate directive
(OpenMP 5.0)."
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603258.html


In his patch set, later patches actually add allocater support for
allocatables/pointers, only – but there issues with regards to the used
allocator (see patches + patch review).

As my attached patch raises a sorry, it neither addresses that issue nor
is it affected by that issue.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit d64e8e1224708e7f5b87c531aeb26f1ed07f91ff
Author: Tobias Burnus 
Date:   Fri May 26 20:39:33 2023 +0200

Fortran/OpenMP: Add parsing support for allocators/allocate directives

gcc/fortran/ChangeLog:

* dump-parse-tree.cc (show_omp_namelist): Update allocator, fix
align dump.
(show_omp_node, show_code_node): Handle EXEC_OMP_ALLOCATE.
* gfortran.h (enum gfc_statement): Add ST_OMP_ALLOCATE and ..._EXEC.
(enum gfc_exec_op): Add EXEC_OMP_ALLOCATE.
(struct gfc_omp_namelist): Add 'allocator' to 'u2' union.
(struct gfc_namespace): Add omp_allocate.
(gfc_resolve_omp_allocate): New.
* match.cc (gfc_free_omp_namelist): Free 'u2.allocator'.
* match.h (gfc_match_omp_allocate, gfc_match_omp_allocators): New.
* openmp.cc (gfc_omp_directives): Uncomment allocate/allocators.
(gfc_match_omp_variable_list): Add bool arg for
rejecting listening common-block vars separately.
(gfc_match_omp_clauses): Update for u2.allocators.
(OMP_ALLOCATORS_CLAUSES, gfc_match_omp_allocate,
gfc_match_omp_allocators, is_predefined_allocator,
gfc_resolve_omp_allocate): New.
(resolve_omp_clauses): Update 'allocate' clause checks.
(omp_code_to_statement, gfc_resolve_omp_directive): Handle
OMP ALLOCATE/ALLOCATORS.
* parse.cc (in_exec_part): New global var.
   

[committed] Re: [Patch,v4] Fortran/OpenMP: Fix mapping of array descriptors and deferred-length strings

2023-05-17 Thread Tobias Burnus

The patch has now been committed as r14-931-g80bb0b8a81fdc5

The only change is that I added the &_P in 'if (sym->ts.deferred &&
VAR_P (length))' in trans-decl.cc just to avoid potential issues in case
length is not a var decl (but e.g. a '0' tree node, cf. code).

Tobias

On 23.03.23 10:28, Tobias Burnus wrote:

[...]

Another update - fixing an independent issue which makes sense to be
part of this
patch.

Allocatable/pointer scalars are currently mapped as:

 #pragma omp target enter data map(to:*var.1_1 [len: 4]) map(alloc:var
[pointer assign, bias: 0])
 #pragma omp target exit data map(from:*var.2_2 [len: 4])

where 'GOMP_MAP_POINTER' is removed in gimplify.cc. In v3 (and v4) of
this patch,
this kind of handling moved from gimplify.cc to
fortran/trans-openmp.cc; however,
v3 has the same problem. For allocatable arrays, we have PSET +
POINTER and
the PSET part is changed/set to RELEASE/DELETE for 'exit data'

But for scalars, the map was still left on the stack. Besides having a
stale map,
this could lead to fails when the stack was popped, especially when
attempting
to later map another stack variable with the same stack address,
partially
overlapping with the stale POINTER.

Side remark:
I found this for testcase that is part of an upcoming deep-mapping
follow-up patch;
that test failed with -O1 but worked with -O0/-Og due to changed stack
usage.
(Deep-mapping of allocatable components is on the OG12 branch; it is
scheduled
for mainline integration after stage1 opened.)


The updated mainline patch is included; map-10.f90 is the new testcase.
If anyone wants to see it separately, the patch has been committed to
OG12 as
https://gcc.gnu.org/g:8ea805840200f7dfd2c11b37abf5fbfe479c2fe2

Comments/thoughts/remarks to this patch?

Tobias

PS: For the rest of the patch, see a short description below - or with
some longer
remarks previous in this thread.

On 27.02.23 13:15, Tobias Burnus wrote:

And another re-diff for GCC 13/mainline, updating gcc/testsuite/

(The last change is related to the "[OG12,committed] Update dg-dump-scan
for ..." discussion + OG12 https://gcc.gnu.org/g:e4de87a2309 /
https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612871.html )

On 23.02.23 17:42, Tobias Burnus wrote:

On 21.02.23 12:57, Tobias Burnus wrote:

This patch moves some generic code for Fortran out of gimplify.cc
to trans-openmp.cc and fixes several issues related to mapping.

Tested with nvptx offloading.
OK for mainline?

Tobias

Caveats:

Besides the issues shown in the comment-out code, there remains
also an
issue with implicit mapping - at least for deferred-length strings,
but I wouldn't be surprised if - at least depending on the used
'defaultmap' value (e.g. 'alloc') - there are also issues with array
descriptors.

Note:

Regarding the declare target check for mapping: Without declare
target, my assumption is that the hidden length variable will
get implicitly mapped if needed. Independent of deferred-length
or not, there is probably an issue with 'defaultmap(none)' and
the hidden variable. - In any case, I prefer to defer all those
issues to later (by having them captured in one/several PR).


Tobias

PS: This patch is a follow up to
  [Patch] Fortran/OpenMP: Fix DT struct-component with 'alloc' and
array descr
https://gcc.gnu.org/pipermail/gcc-patches/2022-November/604887.html
which fixed part of the problems. But as discussed on IRC, it did
treat 'alloc'
as special and missed some other map types. - In addition, this patch
has a
much extended test coverage and fixes some more issues found that way.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 80bb0b8a81fdc5d0a1c88ae3febd593868daa752
Author: Tobias Burnus 
Date:   Wed May 17 12:28:14 2023 +0200

Fortran/OpenMP: Fix mapping of array descriptors and deferred-length strings

Previously, array descriptors might have been mapped as 'alloc'
instead of 'to' for 'alloc', not updating the array bounds. The
'alloc' could also appear for 'data exit', failing with a libgomp
assert. In some cases, either array descriptors or deferred-length
string's length variable was not mapped. And, finally, some offset
calculations with array-sections mappings went wrong.

Additionally, the patch now unmaps for scalar allocatables/pointers
the GOMP_MAP_POINTER, avoiding stale mappings.

The testcases contain some comment-out tests which require follow-up
work and for which PR exist. Those mostly relate to deferred-length
strings which have several issues beyong OpenMP support.

gcc/fortran/ChangeLog:

* trans-decl.cc (gfc_get_symbol_decl): Add attributes
such as 'declare target' also to hidden artificial
variable for 

Re: [PATCH] OpenACC: Further attach/detach clause fixes for Fortran [PR109622]

2023-05-03 Thread Tobias Burnus



On 03.05.23 14:59, Julian Brown wrote:

How does this version look?
Retested with offloading to nvptx.

LGTM (for mainline + GCC 13 backporting) but I have two tiny comments:

diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 86e4515..322856a 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -7711,6 +7711,23 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses 
*omp_clauses,
   >where);
}
}
+ if (openacc
+ && list == OMP_LIST_MAP
+ && (n->u.map_op == OMP_MAP_ATTACH
+ || n->u.map_op == OMP_MAP_DETACH))
+   {
+ symbol_attribute attr;
+ gfc_clear_attr ();
+ if (n->expr)
+   attr = gfc_expr_attr (n->expr);
+ else if (n->sym)
+   attr = n->sym->attr;


Note that n->sym == NULL is only the case if the argument was
omp_all_memory (→ gfc_match_omp_variable_list); that can only be the
case for OMP_CLAUSE_DEPEND.

As OpenMP's 'depend' clause is handled before and you additionally deal
with OpenACC, only, you could just use 'else' instead of 'else if
(n->sym)' – and also get rid of the 'gfc_clear_attr' as the values get
overwritten by the assignment and by the function call.

Later code (e.g. line 7785 in the current code) also assumes (for
OpenACC + MAP) that n->sym != NULL by bluntly dereferencing it.

@@ -3523,15 +3525,20 @@ gfc_trans_omp_clauses (stmtblock_t *block,
gfc_omp_clauses *clauses,

if (n->u.map_op == OMP_MAP_ATTACH
|| n->u.map_op == OMP_MAP_DETACH)
  {
-   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
+   if (POINTER_TYPE_P (TREE_TYPE (inner))
+   || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
  {

...

  }
-   else
- OMP_CLAUSE_DECL (node) = inner;
-   OMP_CLAUSE_SIZE (node) = size_zero_node;
-   goto finalize_map_clause;
  }


You can now combine the two if conditions, which avoids some indenting
and should permit to put 'tree ptr' / ' = ...' again on the same line.

Thanks for the patch!

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH] OpenACC: Further attach/detach clause fixes for Fortran [PR109622]

2023-05-02 Thread Tobias Burnus

On 29.04.23 12:57, Julian Brown wrote:

This patch moves several tests introduced by the following patch:

   https://gcc.gnu.org/pipermail/gcc-patches/2023-April/616939.html


I believe you intent this as git log entry. Can you add
  ... commit r14-325-gcacf65d74463600815773255e8b82b4043432bd7
as this makes looking at the git history easier.


into the proper location for OpenACC testing (thanks to Thomas for
spotting my mistake!), and also fixes a few additional problems --
missing diagnostics for non-pointer attaches, and a case where a pointer
was incorrectly dereferenced. Tests are also adjusted for vector-length
warnings on nvidia accelerators.

Tested with offloading to nvptx. OK?

2023-04-29  Julian Brown  

  PR fortran/109622

gcc/fortran/
  * trans-openmp.cc (gfc_trans_omp_clauses): Add diagnostic for
  non-pointer/non-allocatable attach/detach.  Remove dereference for
  pointer-to-scalar derived type component attach/detach.


In general, we prefer resolution-time diagnostic to tree-translation diagnostic,
unless there is a good reason to do the latter.
At a glance, it should be even sufficient to have a single diagnostic
instead of two when placed into openmp.cc.

Search for lastref in resolve_omp_clauses; I think it should do,
but otherwise something like:
 symbol_attr attr = gfc_expr_attr(e);
 if (attr.pointer || attr.allocatable)
should work.

You currently have:


@@ -3430,6 +3432,13 @@ gfc_trans_omp_clauses (stmtblock_t *block, 
gfc_omp_clauses *clauses,
  = TYPE_SIZE_UNIT (gfc_charlen_type_node);
  }
  }
+   else if (openacc
+&& (n->u.map_op == OMP_MAP_ATTACH
+|| n->u.map_op == OMP_MAP_DETACH))
+ gfc_error ("%qs clause argument not pointer or "
+"allocatable at %L",
+(n->u.map_op == OMP_MAP_ATTACH)
+? "attach" : "detach", );


Additionally, I think we we usually have wording like: 'must be ALLOCATABLE or 
a POINTER'.
(Which avoids also the question whether 'neither' instead of 'not should be used
and/besides to 'nor' instead of 'or'.)

Additionally, I think there should be a also an error for:

integer :: a
!$acc enter data attach(a)
end

(Well, in that case, just looking at n->expr won't work, but also n->sym needs 
to be
handled for list == OMP_LIST_MAP && n->u.map_op == OMP_MAP_(DE)ATTACH.

The other changes look fine. Thanks!

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH] OpenACC: Stand-alone attach/detach clause fixes for Fortran [PR109622]

2023-04-28 Thread Tobias Burnus

On 27.04.23 20:36, Julian Brown wrote:

This patch fixes several cases where multiple attach or detach mapping
nodes were being created for stand-alone attach or detach clauses
in Fortran.  After the introduction of stricter checking later during
compilation, these extra nodes could cause ICEs, as seen in the PR.

The patch also fixes cases that "happened to work" previously where
the user attaches/detaches a pointer to array using a descriptor, and
(I think!) the "_data" field has offset zero, hence the same address as
the descriptor as a whole.

Tested with offloading to nvptx. OK?


LGTM for mainline and, after some grace period, for GCC 13.

Thanks,

Tobias


2023-04-27  Julian Brown  

  PR fortran/109622

gcc/fortran/
  * trans-openmp.cc (gfc_trans_omp_clauses): Attach/detach clause fixes.

gcc/testsuite/
  * gfortran.dg/goacc/attach-descriptor.f90: Adjust expected output.

libgomp/
  * testsuite/libgomp.fortran/pr109622.f90: New test.
  * testsuite/libgomp.fortran/pr109622-2.f90: New test.
  * testsuite/libgomp.fortran/pr109622-3.f90: New test.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[committed] Fortran: Fix (mostly) comment typos

2023-04-28 Thread Tobias Burnus

Committed as r14-319-g7ebd4a1d61993c0a75e9ff3098aded21ef04a4da

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 7ebd4a1d61993c0a75e9ff3098aded21ef04a4da
Author: Tobias Burnus 
Date:   Fri Apr 28 09:23:18 2023 +0200

Fortran: Fix (mostly) comment typos

Only other changes are fixing the variable name a(b)breviated_modproc_decl
and a few typos in gfortran.texi.

gcc/fortran/ChangeLog:

* gfortran.texi: Fix typos.
* decl.cc: Fix typos in comments and in a variable name.
* arith.cc: Fix comment typos.
* check.cc: Likewise.
* class.cc: Likewise.
* dependency.cc: Likewise.
* expr.cc: Likewise.
* frontend-passes.cc: Likewise.
* gfortran.h: Likewise.
* intrinsic.cc: Likewise.
* iresolve.cc: Likewise.
* match.cc: Likewise.
* module.cc: Likewise.
* primary.cc: Likewise.
* resolve.cc: Likewise.
* simplify.cc: Likewise.
* trans-array.cc: Likewise.
* trans-decl.cc: Likewise.
* trans-expr.cc: Likewise.
* trans-intrinsic.cc: Likewise.
* trans-openmp.cc: Likewise.
* trans-stmt.cc: Likewise.

diff --git a/gcc/fortran/arith.cc b/gcc/fortran/arith.cc
index ddf9874671c..d1d814b3ae1 100644
--- a/gcc/fortran/arith.cc
+++ b/gcc/fortran/arith.cc
@@ -1037 +1037 @@ gfc_arith_concat (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
- to get mismaching types here.  */
+ to get mismatching types here.  */
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 8c1ae8c2f00..b348bda6e6c 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -96 +96 @@ illegal_boz_arg (gfc_expr *x)
-/* Some precedures take two arguments such that both cannot be BOZ.  */
+/* Some procedures take two arguments such that both cannot be BOZ.  */
diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index bffc03a..9d0c802b867 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1634 +1634 @@ finalizer_insert_packed_call (gfc_code *block, gfc_finalizer *fini,
-   derived type "derived". The function first calls the approriate FINAL
+   derived type "derived". The function first calls the appropriate FINAL
diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 233bf244d62..9c4b40d4ac4 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -1084 +1084 @@ char_len_param_value (gfc_expr **expr, bool *deferred)
-  /* If gfortran gets an EXPR_OP, try to simplifiy it.  This catches things
+  /* If gfortran gets an EXPR_OP, try to simplify it.  This catches things
@@ -1579 +1579 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
-	 length of 1.  However, as an argument they are also iteroperable
+	 length of 1.  However, as an argument they are also interoperable
@@ -2850 +2850 @@ variable_decl (int elem)
-  /* The dummy arguments and result of the abreviated form of MODULE
+  /* The dummy arguments and result of the abbreviated form of MODULE
@@ -3120 +3120 @@ variable_decl (int elem)
-  /* Before adding a possible initilizer, do a simple check for compatibility
+  /* Before adding a possible initializer, do a simple check for compatibility
@@ -8351 +8351 @@ gfc_match_end (gfc_statement *st)
-  bool abreviated_modproc_decl = false;
+  bool abbreviated_modproc_decl = false;
@@ -8375 +8375 @@ gfc_match_end (gfc_statement *st)
-  abreviated_modproc_decl = gfc_state_stack->previous->sym
+  abbreviated_modproc_decl = gfc_state_stack->previous->sym
@@ -8383,2 +8383,2 @@ gfc_match_end (gfc_statement *st)
-  if (!abreviated_modproc_decl)
-abreviated_modproc_decl = gfc_current_block ()
+  if (!abbreviated_modproc_decl)
+abbreviated_modproc_decl = gfc_current_block ()
@@ -8398 +8398 @@ gfc_match_end (gfc_statement *st)
-  if (!abreviated_modproc_decl)
+  if (!abbreviated_modproc_decl)
@@ -8407 +8407 @@ gfc_match_end (gfc_statement *st)
-  if (!abreviated_modproc_decl)
+  if (!abbreviated_modproc_decl)
@@ -8536 +8536 @@ gfc_match_end (gfc_statement *st)
-			   abreviated_modproc_decl ? "END PROCEDURE"
+			   abbreviated_modproc_decl ? "END PROCEDURE"
@@ -8554 +8554 @@ gfc_match_end (gfc_statement *st)
-  gfc_error ("Expecting %s statement at %L", abreviated_modproc_decl
+  gfc_error ("Expecting %s statement at %L", abbreviated_modproc_decl
diff --git a/gcc/fortran/dependency.cc b/gcc/fortran/dependency.cc
index 9117825ee6e..a648d5c7903 100644
--- a/gcc/fortran/dependency.cc
+++ b/gcc/fortran/dependency.cc
@@ -546 +546 @@ gfc_dep_difference (gfc_expr *e1, gfc_expr *e2, mpz_t 

[committed] gfortran.dg/gomp/affinity-clause-1.f90: Fix scan-tree-dump (was: [r13-7120 Regression] FAIL: gfortran.dg/gomp/affinity-clause-1.f90 -O scan-tree-dump-times original "#pragma omp task affin

2023-04-11 Thread Tobias Burnus

Commit r13-7137 fixes thethe dump issue with -m32, cf. attachment.

Tobias

On 09.04.23 00:11, haochen.jiang via Gcc-patches wrote:

 Fortran: Fix dg directives and remove trailing whitespaces in testsuite
caused
FAIL: gfortran.dg/gomp/affinity-clause-1.f90   -O   scan-tree-dump-times original "#pragma 
omp task affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.[0-9]+:5:1\\):b\\[\\(.* ? 
\\+ -1\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) 
i=D\\.[0-9]+:5:1\\):d\\[\\(\\(integer\\(kind=8\\)\\) i \\+ -1\\) \\* 6\\]\\)" 1

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit b8e32978e3d9e3b88cd4f441edfdebfa395a5c26
Author: Tobias Burnus 
Date:   Tue Apr 11 13:15:39 2023 +0200

gfortran.dg/gomp/affinity-clause-1.f90: Fix scan-tree-dump

Commit r13-7120-g46fe32cb4d887d44a62f9c4ff2a72532d4eb5a19 added the
missing hyphen to 'dg-final', which exposed an -m32 pattern mismatch.

gcc/testsuite/

* gfortran.dg/gomp/affinity-clause-1.f90: Update scan-tree pattern
for -m32.

diff --git a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90 b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90
index b8c7b5d68ad..32c9acef070 100644
--- a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90
@@ -27,2 +27 @@ end
-! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):b\\\[\\(.* ? \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):d\\\[\\(\\(integer\\(kind=8\\)\\) i \\+ -1\\) \\* 6\\\]\\)"  1 "original" } }
-
+! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):b\\\[.* ? \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):d\\\[\\(.*i \\+ -1\\) \\* 6\\\]\\)"  1 "original" } }


[OG12][committed] Fortran/OpenMP: Fix 'alloc' and 'from' mapping for allocatable components

2023-03-23 Thread Tobias Burnus

This is about OpenMP's "deep mapping" of allocatable components of derived 
types.

The basic feature is on OG12 (and OG11) but yet in GCC mainline. The old
submissions are at 
https://gcc.gnu.org/pipermail/gcc-patches/2022-April/593704.html

My plan is to get the whole feature into GCC 14 once trunk has opened (and
after some simpler pending patches have been merged). It requires some
re-diffing to be more digestible.

* * *

OG12: This patch as been committed to the devel/omp/gcc-12 branch as
https://gcc.gnu.org/g:a63735b8034db65a33c359633462accd9d71d3b5

* * *

This patch fixes an issue with 'map(alloc:' and 'map(from:' with
deep mapping of allocatable components - namely:

* For unmapping/coping to the host, the state of unallocated allocatables
  needs to be preservered.
* For mapping to the device ('alloc' and 'from'), we still need to copy
  data to the device to have the array bounds correctly set.

The data pointer (of allocated allocatables) is set as part of allocating
memory on the device ('attach'); thus, this part works.

As described in the patch (cf. comment above the checking function), we
could either copy only the descriptor data (and the NULL for pointers)
or we copy everything (shallowly) which includes this data. As there is
no means to do the former (without changing the refcount), we do the latter.

NOTE: The actual data to which the scalar/array allocatable points to is
not 'to' mapped but only 'alloc'. As that is supposed to be the large data,
copying everything should™ not cause a large performance penalty with real-world
code; it could be even faster than, let's say, copying 5 descriptors separately.

OpenMP spec side: It is not completely clear how the OpenMP spec expects
the copy out to work. Hence, I filed OpenMP Spec Issue #3545.
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit a63735b8034db65a33c359633462accd9d71d3b5
Author: Tobias Burnus 
Date:   Thu Mar 23 18:04:17 2023 +0100

Fortran/OpenMP: Fix 'alloc' and 'from' mapping for allocatable components

Even with 'alloc' and map-entering 'from' mapping, the following should hold.
For explicit mapping, that's already the case, this handles the automatical
deep mapping of allocatable components. Namely:
* On the device, the array bounds (of allocated allocatables) must match the
  host, implying 'to' (or 'tofrom') mapping.
* On map exiting, the copying out shall not destroy the unallocated allocation
  status (nor the pointer address of allocated allocatables).

The latter was not a problem for allocated allocatables as for those a pointer
was GOMP_MAP_ATTACHed; however, for unallocated allocatables, before it copied
back device-allocated memory which might not be nullified.

While 'alloc' was not deep-mapped at all, for map-entering 'from', the array
bounds were not set, making allocated derived-type components inaccessible on
the device (and wrong on the host on copy back).

The solution is, first, to deep-map 'alloc' as well and to copy to the device
even with 'alloc' and (map-entering) 'from'. This copying is only done if there
is a scalar (for the unallocated case) or array allocatable directly in the
derived type and then it is shallowly copied; the data pointed to is then again
only alloc'ed, unless it contains in turn allocatables.

gcc/fortran/

* trans-openmp.cc (gfc_has_alloc_comps): Add 'bool
shallow_alloc_only=false' arg.
(gfc_omp_replace_alloc_by_to_mapping): New, call it.
(gfc_omp_deep_map_kind_p): Return 'true' also for '(present,)alloc'.
(gfc_omp_deep_mapping_item, gfc_omp_deep_mapping_do): On map entering,
replace shallowly 'alloc'/'from' by '(from)to' mapping if there are
allocatable components.

libgomp/

* testsuite/libgomp.fortran/map-alloc-comp-8.f90: New test.
---
 gcc/fortran/ChangeLog.omp  |  10 +
 gcc/fortran/trans-openmp.cc|  96 +++-
 libgomp/ChangeLog.omp  |   4 +
 .../testsuite/libgomp.fortran/map-alloc-comp-8.f90 | 268 +
 4 files changed, 371 insertions(+), 7 deletions(-)

diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp
index f7d1f91f178..e3ab2254215 100644
--- a/gcc/fortran/ChangeLog.omp
+++ b/gcc/fortran/ChangeLog.omp
@@ -1,3 +1,13 @@
+2023-03-23  Tobias Burnus  
+
+	* trans-openmp.cc (gfc_has_alloc_comps): Add 'bool
+	shallow_alloc_only=false' arg.
+	(gfc_omp_replace_alloc_by_to_mapping): New, call it.
+	(gfc_omp_deep_map_kind_p): Return 'true' also for '(present,)alloc'.
+	(gfc_omp_deep_mapping_item, gfc_omp_deep_mapping_do): On ma

[OG12][committed] Fortran: Add attr.class_ok check for generate_callback_wrapper

2023-03-23 Thread Tobias Burnus

On OG12, the OpenMP deep-mapping support added a callback procedure to the 
vtable.
That one did not handle error recovery well (ICE when a CLASS component as not 
(class_)ok.

The attached patch has been committed as 
https://gcc.gnu.org/g:9c18db65914a751e4a1d9330ccc1659fe5ef270d
and applies only to OG12 (= git branch devel/omp/gcc-12) as mainline does not 
have this
code (yet).

* * *

The plan is to upstream the deep-mapping support, i.e. mapping of allocatable 
components.
The current OG12 implementation handles both mapping the declared type and the 
dynamic type,
the latter requires the wrapper, generated by generate_callback_wrapper.

I plan to upstream first the static part - and only then think about the 
wrapper. I think
the wrapper could be useful for coarrays as well - namely, for the user-defined 
reduction,
but I have not fully thought about it. It would break the ABI as the vtable 
gets another
entry before the type-bound procedures, which is why I am a bit hesitant; it it 
gets merged,
we it would be the opportunity to change some other things as well - like: 
generating the
CLASS functions/vtable only when used. (→ weak symbols to permit it in multiple 
translation
units; storing the fact that it has been generated in the module.)
But that's offtopic.

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
commit 9c18db65914a751e4a1d9330ccc1659fe5ef270d
Author: Tobias Burnus 
Date:   Thu Mar 23 14:29:00 2023 +0100

Fortran: Add attr.class_ok check for generate_callback_wrapper

Proper variables/components of type BT_CLASS have 'class_ok' set; check
for that to avoid an ICE on invalid code for gfortran.dg/pr108434.f90.

gcc/fortran/
* class.cc (generate_callback_wrapper): Add attr.class_ok check.
* resolve.cc (resolve_fl_derived): Likewise.

diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp
index 663102d9329..f7d1f91f178 100644
--- a/gcc/fortran/ChangeLog.omp
+++ b/gcc/fortran/ChangeLog.omp
@@ -1,3 +1,8 @@
+2023-03-23  Tobias Burnus  
+
+	* class.cc (generate_callback_wrapper): Add attr.class_ok check.
+	* resolve.cc (resolve_fl_derived): Likewise.
+
 2023-03-23  Tobias Burnus  
 
 	* trans-openmp.cc (gfc_trans_omp_clauses): Fix unmapping of
diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index 35dc35d2ee6..7ab6923523f 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -2550,6 +2550,9 @@ generate_callback_wrapper (gfc_symbol *vtab, gfc_symbol *derived,
 	 cb (token, comp->var(.data), size, 0, var's cb fn);  */
   for (gfc_component *comp = derived->components; comp; comp = comp->next)
 {
+  if (__builtin_expect (comp->ts.type == BT_CLASS
+			&& !comp->attr.class_ok, 0))
+	continue;
   bool pointer = (comp->ts.type == BT_CLASS
 		  ? CLASS_DATA (comp)->attr.pointer : comp->attr.pointer);
   bool proc_ptr = comp->attr.proc_pointer;
@@ -2590,7 +2593,7 @@ generate_callback_wrapper (gfc_symbol *vtab, gfc_symbol *derived,
 	  size->where = gfc_current_locus;
 	}
 
-  if (!proc_ptr && comp->ts.type == BT_CLASS)
+  if (!proc_ptr && comp->ts.type == BT_CLASS && comp->attr.class_ok)
 	{
 	  gfc_add_data_component (expr);
 	  if (comp->attr.dimension)
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index aaeaf396b91..15db1252366 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -15173,7 +15173,8 @@ resolve_fl_derived (gfc_symbol *sym)
   gfc_component *c = (sym->attr.is_class
 		  ? CLASS_DATA (sym->components) : sym->components);
   for ( ; c; c = c->next)
-if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
+if ((c->ts.type == BT_DERIVED
+	|| (c->ts.type == BT_CLASS && c->attr.class_ok))
 	&& !c->ts.u.derived->resolve_symbol_called)
   {
 	if (c->ts.u.derived->components == NULL


[Patch,v4] Fortran/OpenMP: Fix mapping of array descriptors and deferred-length strings

2023-03-23 Thread Tobias Burnus

[GCC 13 vs GCC 14]
I am unsure whether this should still go to GCC 13 or not. It is somewhat larger
albeit well contained (Fortran, only OpenMP, ...) and fixes real-world bugs,
but it is not a regression - and we are meanwhile slowly approaching the 
release.

An alternative would be to go to GCC 14 and then be eventually backported to 
GCC 14
(albeit I am not sure whether early testing would be better). Or just to GCC 
14, hmm.

Thoughts?

* * *

Another update - fixing an independent issue which makes sense to be part of 
this
patch.

Allocatable/pointer scalars are currently mapped as:

 #pragma omp target enter data map(to:*var.1_1 [len: 4]) map(alloc:var [pointer 
assign, bias: 0])
 #pragma omp target exit data map(from:*var.2_2 [len: 4])

where 'GOMP_MAP_POINTER' is removed in gimplify.cc. In v3 (and v4) of this 
patch,
this kind of handling moved from gimplify.cc to fortran/trans-openmp.cc; 
however,
v3 has the same problem. For allocatable arrays, we have PSET + POINTER and
the PSET part is changed/set to RELEASE/DELETE for 'exit data'

But for scalars, the map was still left on the stack. Besides having a stale 
map,
this could lead to fails when the stack was popped, especially when attempting
to later map another stack variable with the same stack address, partially
overlapping with the stale POINTER.

Side remark:
I found this for testcase that is part of an upcoming deep-mapping follow-up 
patch;
that test failed with -O1 but worked with -O0/-Og due to changed stack usage.
(Deep-mapping of allocatable components is on the OG12 branch; it is scheduled
for mainline integration after stage1 opened.)


The updated mainline patch is included; map-10.f90 is the new testcase.
If anyone wants to see it separately, the patch has been committed to OG12 as
https://gcc.gnu.org/g:8ea805840200f7dfd2c11b37abf5fbfe479c2fe2

Comments/thoughts/remarks to this patch?

Tobias

PS: For the rest of the patch, see a short description below - or with some 
longer
remarks previous in this thread.

On 27.02.23 13:15, Tobias Burnus wrote:

And another re-diff for GCC 13/mainline, updating gcc/testsuite/

(The last change is related to the "[OG12,committed] Update dg-dump-scan
for ..." discussion + OG12 https://gcc.gnu.org/g:e4de87a2309 /
https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612871.html )

On 23.02.23 17:42, Tobias Burnus wrote:

On 21.02.23 12:57, Tobias Burnus wrote:

This patch moves some generic code for Fortran out of gimplify.cc
to trans-openmp.cc and fixes several issues related to mapping.

Tested with nvptx offloading.
OK for mainline?

Tobias

Caveats:

Besides the issues shown in the comment-out code, there remains also an
issue with implicit mapping - at least for deferred-length strings,
but I wouldn't be surprised if - at least depending on the used
'defaultmap' value (e.g. 'alloc') - there are also issues with array
descriptors.

Note:

Regarding the declare target check for mapping: Without declare
target, my assumption is that the hidden length variable will
get implicitly mapped if needed. Independent of deferred-length
or not, there is probably an issue with 'defaultmap(none)' and
the hidden variable. - In any case, I prefer to defer all those
issues to later (by having them captured in one/several PR).


Tobias

PS: This patch is a follow up to
  [Patch] Fortran/OpenMP: Fix DT struct-component with 'alloc' and
array descr
https://gcc.gnu.org/pipermail/gcc-patches/2022-November/604887.html
which fixed part of the problems. But as discussed on IRC, it did
treat 'alloc'
as special and missed some other map types. - In addition, this patch
has a
much extended test coverage and fixes some more issues found that way.

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
Fortran/OpenMP: Fix mapping of array descriptors and deferred-length strings

Previously, array descriptors might have been mapped as 'alloc'
instead of 'to' for 'alloc', not updating the array bounds. The
'alloc' could also appear for 'data exit', failing with a libgomp
assert. In some cases, either array descriptors or deferred-length
string's length variable was not mapped. And, finally, some offset
calculations with array-sections mappings went wrong.

Additionally, the patch now unmaps for scalar allocatables/pointers
the GOMP_MAP_POINTER, avoiding stale mappings.

The testcases contain some comment-out tests which require follow-up
work and for which PR exist. Those mostly relate to deferred-length
strings which have several issues beyong OpenMP support.

gcc/fortran/ChangeLog:

	* trans-decl.cc (gfc_get_symbol_decl): Add attributes
	such as 'declare target' also to hidden artificial
	variable for deferred-length character variables.
	* trans-openmp.cc (gfc_trans_omp_array_section,
	gfc_trans_o

Re: [PATCHv4, gfortran] Escalate failure when Hollerith constant to real conversion fails [PR103628]

2023-03-21 Thread Tobias Burnus

Hi,

LGTM, except for:

On 21.03.23 07:29, HAO CHEN GUI wrote:

@@ -4708,7 +4710,12 @@ do_simplify (gfc_intrinsic_sym *specific, gfc_expr *e)

  finish:
if (result == _bad_expr)
-return false;
+{
+  if (errorcount == old_errorcount
+   && (!gfc_buffered_p () && !gfc_error_flag_test ()))
+   gfc_error ("Cannot simplify expression at %L", >where);
+  return false;
+}


The second line of the condition now tests:
* 'If buffering is disabled and no pending buffed error exists
   then show an error'

But if should tests:
* 'If (buffering is disabled) OR ((it is enabled but) no buffered error exists)
  then show¹ an error'

Thus, you should use an '||' not a '&&':

+ && (!gfc_buffered_p () || !gfc_error_flag_test ()))

as proposed in previous email. A quick regtesting shows no fails when doing so.

OK with that change.


(¹or rather: 'then buffer an error')

Thanks for the patch!

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH] Fortran: reject MODULE PROCEDURE outside generic module interface [PR99036]

2023-03-21 Thread Tobias Burnus

On 20.03.23 21:57, Harald Anlauf via Gcc-patches wrote:

--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -9998,6 +9998,7 @@ gfc_match_modproc (void)
if ((gfc_state_stack->state != COMP_INTERFACE
 && gfc_state_stack->state != COMP_CONTAINS)
|| gfc_state_stack->previous == NULL
+  || !current_interface.type
|| current_interface.type == INTERFACE_NAMELESS
|| current_interface.type == INTERFACE_ABSTRACT)
  {


First, I do not like '!var' comparisons for enum values,
only for Booleans/logicals and pointer.

Secondly, I am not sure that it is really guaranteed that
the value is 0.

I think something like the following makes more sense
and, as just tried, it also regtests (w/ your testcase included).
If you agree, feel free to package and commit it.


diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index c8f0bb83c2c..233bf244d62 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -9996,7 +9996,8 @@ gfc_match_modproc (void)
   gfc_interface *old_interface_head, *interface;

-  if ((gfc_state_stack->state != COMP_INTERFACE
-   && gfc_state_stack->state != COMP_CONTAINS)
-  || gfc_state_stack->previous == NULL
+  if (gfc_state_stack->previous == NULL
+  || (gfc_state_stack->state != COMP_INTERFACE
+ && (gfc_state_stack->state != COMP_CONTAINS
+ || gfc_state_stack->previous->state != COMP_INTERFACE))
   || current_interface.type == INTERFACE_NAMELESS
   || current_interface.type == INTERFACE_ABSTRACT)


Thanks for working on this and all the other issues!

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCHv3, gfortran] Escalate failure when Hollerith constant to real conversion fails [PR103628]

2023-03-20 Thread Tobias Burnus

Hi,

sorry for the belated reply.

On 07.03.23 09:55, HAO CHEN GUI wrote:

2023-03-07  Haochen Gui 

gcc/
  PR target/103628
  * fortran/target-memory.cc (gfc_interpret_float): Return FAIL when
  native_interpret_expr gets a NULL tree.
  * fortran/arith.cc (gfc_hollerith2real): Return NULL when
  gfc_interpret_float fails.
  * fortran/error.cc (gfc_buffered_p): Define.
  * fortran/gfortran.h (gfc_buffered_p): Declare.
  * fortran/intrinsic.cc: Add diagnostic.h to include list.
  (do_simplify): Save errorcount and check it at finish.  Report a
  "Cannot simplify expression" error on a bad result if error count
  doesn't change and no other errors buffered.

gcc/testsuite/
  PR target/103628
  * gfortran.dg/pr103628.f90: New.

Co-Authored-By: Tobias Burnus 

...

--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc

...

@@ -4708,7 +4710,12 @@ do_simplify (gfc_intrinsic_sym *specific, gfc_expr *e)

  finish:
if (result == _bad_expr)
-return false;
+{
+  if (errorcount == old_errorcount
+   && (gfc_buffered_p () && !gfc_error_flag_test ()))
+   gfc_error ("Cannot simplify expression at %L", >where);
+  return false;
+}


The condition looks wrong. Shouldn't it be something like

+ && (!gfc_buffered_p () || !gfc_error_flag_test ()))

Namely:
* If there is no buffering, we know that no error has been printed → call error.
* With buffering, we additionally need to check for buffered errors.
  No buffered error → call error.

Otherwise LGTM.

Thus, if my comment makes sense to you + it regtests, modify it, and
go ahead and commit it.

Sorry for the delay - and thanks again for the patch!

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [PATCH] Fortran: rank checking with explicit-/assumed-size arrays and CLASS [PR58331]

2023-03-15 Thread Tobias Burnus

Hi Harald,

On 14.03.23 20:38, Harald Anlauf wrote:

The testcase covers only non-coarray cases, as playing with
coarray variants hit pre-exisiting issues in gfortran that
are very likely unrelated to the interface checks.

I concur (but would not rule out additional interface issues).

I consider this rather as post 13-release stuff.

In any case, the coarray issue can be fixed separately. And I think
post-GCC-13 makes sense.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

Thanks – LGTM!

+  formal_as = formal->ts.type == BT_CLASS ? CLASS_DATA (formal)->as
+   : formal->as;
+


(Jakub remarks for such code that some editor (emacs?), he does not use,
mis--auto-indent such a code - and proposes to add a parentheses
around the right-hand side of the assignment.)

* * *

I also wonder whether we need some run-time testcase. The interface
check now works and I also tend to write dg-do-compile testcases, but
given what can go wrong with all the array descriptor, class etc
handling, we may want to ensure it works at run time. – Thoughts?

(That's independent of the patch it and could be done as follow up, if
it deemed reasonable. The included testcase is surely compile-only as it
has dg-error checks.)

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: [Patch, fortran] PR37336 finalization

2023-03-08 Thread Tobias Burnus

On 08.03.23 16:12, Steve Kargl via Fortran wrote:

For one of my codes, I see
% foreach i (*.o)
foreach? nm $i | grep final
foreach? end
0280 T __beamsm_MOD___final_beamsm_Table_t
0580 T __bsam_MOD___final_bsam_Bsa_info_t
01e0 T __bsam_MOD___final_bsam_Bsa_t
00a0 T __ffn_data_MOD___final_ffn_data_Fe_t

I do not explicitly use finalization nor do I have
subprograms named __final_*.  To me, this re-inforces
Richard's point about not breaking existing code.


I think there are two places where finalization is touched: (a) when
declaring a type, finalization procedures might get generated.(*) — And,
(b) invoking finalization procedures.

(a) happens if you have you explicitly add finalization functions – or
(I believe) when you have allocatable components as GCC may then need to
free them.

I think (b) only happens if you either have polymorphism (as then you
don't know whether the polymorphic function uses finalization) – or when
you invoke explicitly finalization.

I believe you run into (a) – the finalization generation. My
understanding is that Paul's patch is mostly about (b) and for sure not
for the default-generated procedures. But of course, any code one
touches for one purpose can still have side effects, affecting seemingly
unrelated code.

Tobias

PS: I think we should change at some point when the virtual tables and
their default procs (init, copy, finalize) generated.

Namely, instead of generating them for all types – even if not used – it
makes sense to generate them only when a type is used in CLASS(t). This
will lead to the generation in multiple translation units, but weak
symbols come to a rescue – and for a MODULE, it can be stored in the
.mod file that the vtable + funcs has been generated. That way, way
fewer vtables are generated, saving a lot of space and reducing compile
time!

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


Re: Request for participation in GSoC

2023-03-08 Thread Tobias Burnus

Hello,

welcome to the GCC/gfortran community.

On 08.03.23 14:02, Martin Jambor wrote:

On Sat, Mar 04 2023, Priyabrata Mondal via Gcc wrote:

I want to
participate in Google Summer of Code 2023 by contributing to the *Fortran –
DO CONCURRENT* project, an implementation of loop that executes
concurrently. I have started to learn about parallel programming and
Fortran programming language.
  I have good knowledge of C, C++, Javascript, HTML, and CSS.
 can you suggest some resources so I can learn the technologies
that are required for this project?
  I will be highly grateful to you forever if you allow me to do
this project under your guidance.

I assume you have read through
   https://gcc.gnu.org/wiki/SummerOfCode#Before_you_apply
have you managed to complete the steps outlined there?


I wrote the following the other day regarding 'do concurrent':

I think there are two parts to it: First, to add the changes of newer
Fortran to gfortran and then to actually use them to generate
concurrently running code. (Internally, gfortran currently handles 'do
concurrent' to run mostly like a normal loop – except that it annotates
the loops are independent. – Real parallelization would be useful, however.)

If you want to see examples, see do_concurrent_1.f90 to
do_concurrent_6.f90 in gfortran's testsuite, i.e.
gcc/testsuite/gfortran.dg/ in the GCC sources. That's at
https://gcc.gnu.org/git/?p=gcc.git;a=tree;f=gcc/testsuite/gfortran.dg;hb=refs/heads/master
/ But it is best to download GCC yourself via Git as described at
https://gcc.gnu.org/git.html

I want to note that the DO CONCURRENT syntax also permits a mask
argument, like in 'do concurrent (i=1:5, j=1:5, (i/=j))' where the last
argument selects a subset.

For the Fortran standard, see https://gcc.gnu.org/wiki/GFortranStandards

Fortran 2018 (= 18-007r1) adds for locality specifiers: LOCAL,
LOCAL_INIT, SHARED and DEFAULT(NONE).

Fortran 202x alias 2023 adds 'reduce' as in 'do concurrent (i = 1, n)
reduce(+:a, b, c) reduce(max:d, e, f)'

I think the first step is to add parsing support for those new features,
i.e. store them, check for issues (diagnostic) and then fail with a
'sorry not yet implemented'.

The next step would be to implement LOCAL/LOCAL_INIT for running on the
host.

And then, finally, would be to translate into code which can then be run
concurrently. I was thinking of mapping it internally to OpenMP or
OpenACC, to be toggled via a commandline option like
-fdo-concurrent=.

* * *

And for getting started with GCC, I wrote:

I think the first step would be to download GCC and build it. Something
like "git clone" as described above, then "mkdir build" (some
directory); "cd build" and then "../configure --prefix=where-to-install"
followed by "make -j12" and "make install". The "-j12" runs 12 build
jobs in parallel. How much to use depends on your system.

You probably need to install some development versions of libraries such
as ISL, gmp, mpfr and mpc. If you don't have them readily, an option is
to run ./contrib/download_prerequisites to download those and build them
automatically alongside GCC.

I hope it helps to get started

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


  1   2   3   4   5   6   >