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

2023-12-11 Thread Andrew MacLeod



On 12/11/23 17:12, Thomas Schwinge wrote:

Hi!

This issue would've been prevented if we'd actually use a distinct C++
data type for GCC types, checkable at compile time -- I'm thus CCing
Andrew MacLeod for amusement or crying, "one more for the list!".  ;-\


Perhaps the time has come  It is definitely under re-consideration 
for next stage 1...


Andrew


(See

"[TTYPE] Strongly typed tree project. Original document circa 2017".)

On 2023-12-11T12:45:27+0100, Tobias Burnus  wrote:

I included a minor cleanup patch [...]

I intent to commit that patch as obvious, unless there are further comments.
OpenMP: Minor '!$omp allocators' cleanup
--- 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", fn);
-/* FIXME: attributes.  */
+  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);
  }
return build_call_expr_loc (input_location, fn, 1, ptr);
  }

Pushed to master branch commit 453e0f45a49f425992bc47ff8909ed8affc29d2e
"Resolve ICE in 'gcc/fortran/trans-openmp.cc:gfc_omp_call_is_alloc'", see
attached.


Grüße
  Thomas


-
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: Minor '!$omp allocators' cleanup - and still: Re: [patch] OpenMP/Fortran: Implement omp allocators/allocate for ptr/allocatables

2023-12-11 Thread Thomas Schwinge
Hi!

This issue would've been prevented if we'd actually use a distinct C++
data type for GCC types, checkable at compile time -- I'm thus CCing
Andrew MacLeod for amusement or crying, "one more for the list!".  ;-\
(See

"[TTYPE] Strongly typed tree project. Original document circa 2017".)

On 2023-12-11T12:45:27+0100, Tobias Burnus  wrote:
> I included a minor cleanup patch [...]
>
> I intent to commit that patch as obvious, unless there are further comments.

> OpenMP: Minor '!$omp allocators' cleanup

> --- 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", fn);
> -/* FIXME: attributes.  */
> +  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);
>  }
>return build_call_expr_loc (input_location, fn, 1, ptr);
>  }

Pushed to master branch commit 453e0f45a49f425992bc47ff8909ed8affc29d2e
"Resolve ICE in 'gcc/fortran/trans-openmp.cc:gfc_omp_call_is_alloc'", see
attached.


Grüße
 Thomas


-
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 453e0f45a49f425992bc47ff8909ed8affc29d2e Mon Sep 17 00:00:00 2001
From: Thomas Schwinge 
Date: Mon, 11 Dec 2023 22:52:54 +0100
Subject: [PATCH] Resolve ICE in
 'gcc/fortran/trans-openmp.cc:gfc_omp_call_is_alloc'

Fix-up for recent commit 2505a8b41d3b74a545755a278f3750a29c1340b6
"OpenMP: Minor '!$omp allocators' cleanup", which caused:

{+FAIL: gfortran.dg/gomp/allocate-5.f90   -O  (internal compiler error: tree check: expected class 'type', have 'declaration' (function_decl) in gfc_omp_call_is_alloc, at fortran/trans-openmp.cc:8386)+}
[-PASS:-]{+FAIL:+} gfortran.dg/gomp/allocate-5.f90   -O  (test for excess errors)

..., and similarly in 'libgomp.fortran/allocators-1.f90',
'libgomp.fortran/allocators-2.f90', 'libgomp.fortran/allocators-3.f90',
'libgomp.fortran/allocators-4.f90', 'libgomp.fortran/allocators-5.f90'.

	gcc/fortran/
	* trans-openmp.cc (gfc_omp_call_is_alloc): Resolve ICE.
---
 gcc/fortran/trans-openmp.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 95184920cf7..f7c73a5d273 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -8381,10 +8381,10 @@ 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", fn);
   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_is_alloc", fn);
 }
   return build_call_expr_loc (input_location, fn, 1, ptr);
 }
-- 
2.34.1



[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] OpenMP/Fortran: Implement omp allocators/allocate for ptr/allocatables

2023-12-09 Thread Jakub Jelinek
On Sat, Dec 09, 2023 at 12:19:10PM +0100, Thomas Schwinge wrote:
> > --- a/gcc/omp-builtins.def
> > +++ b/gcc/omp-builtins.def
> > @@ -467,6 +467,9 @@ DEF_GOMP_BUILTIN 
> > (BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER,
> >  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC,
> > "GOMP_alloc", BT_FN_PTR_SIZE_SIZE_PTRMODE,
> > ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
> > +DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REALLOC,
> > +   "omp_realloc", BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE,
> > +   ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST)
> >  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE,
> > "GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
> >  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WARNING, "GOMP_warning",
> 
> Should this either be 'BUILT_IN_OMP_REALLOC' ('OMP' instead of 'GOMP'),
> or otherwise a 'GOMP_realloc' be added to 'libgomp/allocator.c', like for
> 'GOMP_alloc', 'GOMP_free'; 'ialias_call'ing the respective 'omp_[...]'
> functions?  (Verbatim 'omp_realloc' also mentioned in the comment before
> 'gcc/fortran/trans-openmp.cc:gfc_omp_call_is_alloc'.)

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)

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.  And yes, 3) would be an argument to add
GOMP_realloc.

Jakub



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

2023-12-09 Thread Thomas Schwinge
Hi Tobias!

On 2023-11-08T17:58:10+0100, Tobias Burnus  wrote:
> OpenMP/Fortran: Implement omp allocators/allocate for ptr/allocatables

Nice work!

> This commit adds -fopenmp-allocators which enables support for
> 'omp allocators' and 'omp allocate' that are associated with a Fortran
> allocate-stmt. If such a construct is encountered, an error is shown,
> unless the -fopenmp-allocators flag is present.
>
> With -fopenmp -fopenmp-allocators, those constructs get turned into
> GOMP_alloc allocations, while -fopenmp-allocators (also without -fopenmp)
> ensures deallocation and reallocation (via intrinsic assignments) are
> properly directed to GOMP_free/omp_realloc - while normal Fortran
> allocations are processed by free/realloc.
>
> In order to distinguish a 'malloc'ed from a 'GOMP_alloc'ed memory, the
> version field of the Fortran array discriptor is (mis)used: 0 indicates
> the normal Fortran allocation while 1 denotes GOMP_alloc. For scalars,
> there is record keeping in libgomp: GOMP_add_alloc(ptr) will add the
> pointer address to a splay_tree while GOMP_is_alloc(ptr) will return
> true it was previously added but also removes it from the list.
>
> Besides Fortran FE work, BUILT_IN_GOMP_REALLOC is no part of
> omp-builtins.def and libgomp gains the mentioned two new function.

Minor comments:

> --- a/gcc/fortran/trans-openmp.cc
> +++ b/gcc/fortran/trans-openmp.cc

> +/* Add ptr for tracking as being allocated by GOMP_alloc. */
> +
> +tree
> +gfc_omp_call_add_alloc (tree ptr)
> +{
> +  static tree fn = NULL_TREE;
> +  if (fn == NULL_TREE)
> +{
> +  fn = build_function_type_list (void_type_node, ptr_type_node, 
> NULL_TREE);
> +  fn = build_fn_decl ("GOMP_add_alloc", fn);
> +/* FIXME: attributes.  */
> +}
> +  return build_call_expr_loc (input_location, fn, 1, ptr);
> +}
> +
> +/* Generated function returns true when it was tracked via GOMP_add_alloc and
> +   removes it from the tracking.  As called just before GOMP_free or 
> omp_realloc
> +   the pointer is or might become invalid, thus, it is always removed. */
> +
> +tree
> +gfc_omp_call_is_alloc (tree ptr)
> +{
> +  static tree fn = NULL_TREE;
> +  if (fn == NULL_TREE)
> +{
> +  fn = build_function_type_list (boolean_type_node, ptr_type_node,
> +  NULL_TREE);
> +  fn = build_fn_decl ("GOMP_is_alloc", fn);
> +/* FIXME: attributes.  */
> +}
> +  return build_call_expr_loc (input_location, fn, 1, ptr);
> +}

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

> --- a/gcc/omp-builtins.def
> +++ b/gcc/omp-builtins.def
> @@ -467,6 +467,9 @@ DEF_GOMP_BUILTIN 
> (BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER,
>  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC,
> "GOMP_alloc", BT_FN_PTR_SIZE_SIZE_PTRMODE,
> ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
> +DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REALLOC,
> +   "omp_realloc", BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE,
> +   ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST)
>  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE,
> "GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
>  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WARNING, "GOMP_warning",

Should this either be 'BUILT_IN_OMP_REALLOC' ('OMP' instead of 'GOMP'),
or otherwise a 'GOMP_realloc' be added to 'libgomp/allocator.c', like for
'GOMP_alloc', 'GOMP_free'; 'ialias_call'ing the respective 'omp_[...]'
functions?  (Verbatim 'omp_realloc' also mentioned in the comment before
'gcc/fortran/trans-openmp.cc:gfc_omp_call_is_alloc'.)

> --- a/libgomp/allocator.c
> +++ b/libgomp/allocator.c

> +/* Add pointer as being alloced by GOMP_alloc.  */
> +void
> +GOMP_add_alloc (void *ptr)
> +{
> +  [...]
> +}
> +
> +/* Remove pointer, either called by FREE or by REALLOC,
> +   either of them can change the allocation status.  */
> +bool
> +GOMP_is_alloc (void *ptr)
> +{
> +  [...]
> +}

> --- a/libgomp/libgomp.map
> +++ b/libgomp/libgomp.map

> +GOMP_5.1.2 {
> +  global:
> + GOMP_add_alloc;
> + GOMP_is_alloc;
> + [...]
> +} GOMP_5.1.1;

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


Grüße
 Thomas
-
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/Fortran: Implement omp allocators/allocate for ptr/allocatables

2023-12-08 Thread Jakub Jelinek
On Wed, Nov 08, 2023 at 05:58:10PM +0100, Tobias Burnus wrote:
> --- a/gcc/builtins.cc
> +++ b/gcc/builtins.cc
> @@ -11739,6 +11739,7 @@ builtin_fnspec (tree callee)
>   return ".cO ";
>/* Realloc serves both as allocation point and deallocation point.  */
>case BUILT_IN_REALLOC:
> +  case BUILT_IN_GOMP_REALLOC:
>   return ".Cw ";

I must say I've never been sure if one needs to specify those ". " for
integral arguments for which nothing is known; if they would need to be,
then also all the BUILT_IN_GOMP_* other cases would be wrong, but not just
those, also BUILT_IN_*_CHK (which have extra size_t argument) or
here BUILT_IN_REALLOC itself.  So, let's hope it is ok as is.

Otherwise, the middle-end changes look just fine to me, and for Fortran
FE I'm afraid you know it much more than I do.

Jakub



[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