Re: [Fortran, Patch, PR86468, v1] Follow up: Remove obsolete VIEW_CONVERT

2024-08-23 Thread Andre Vehreschild
Hi Steve,

thanks for the ok. Committed as gcc-15-3099-g0636de8c520

Thanks again,
Andre

On Wed, 21 Aug 2024 09:31:55 -0700
Steve Kargl  wrote:

> On Wed, Aug 21, 2024 at 12:17:46PM +0200, Andre Vehreschild wrote:
> >
> > attached small patch removes a VIEW_CONVERT that I erroneously inserted
> > during patching pr110033. PR86468 fixes the (co-)rank computation and
> > therefore this VIEW_CONVERT is IMO obsolete. I think it may cause hard to
> > find runtime bugs in the future and therefore like to remove it.
> >
> > Regtests ok on x86_64-pc-linux-gnu. Ok for mainline?
> >
>
> Yes.
>


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


[pushed] fortran: Minor fix to -ffrontend-optimize description (was: typo on homepage)

2024-08-23 Thread Gerald Pfeifer
On Mon, 8 Apr 2024, Johannes Nendwich via Gcc wrote:
> on https://gcc.gnu.org/onlinedocs/gfortran/Code-Gen-Options.html
> there is at the end the part
> 
>-ffrontend-optimize
> 
>This option performs front-end optimization, based on manipulating
> parts the Fortran parse tree.
> 
> Might it be that it should say "... manipulating parts _of_ the Fortran 
> parse tree."?

Yes, I believe you're right, so went ahead and pushed the following 
change.

Thank you,
Gerald


commit a071fcda136d00f8321d0adc773007f4f45020ea
Author: Gerald Pfeifer 
Date:   Fri Aug 23 10:02:15 2024 +0200

fortran: Minor fix to -ffrontend-optimize description

gcc/fortran:
* invoke.texi (Code Gen Options): Add a missing word.

diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 6bc42afe2c4..8b3f8118848 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -2117,7 +2117,7 @@ if @option{-ffrontend-optimize} is in effect.
 @cindex Front-end optimization
 @item -ffrontend-optimize
 This option performs front-end optimization, based on manipulating
-parts the Fortran parse tree.  Enabled by default by any @option{-O} option
+parts of the Fortran parse tree.  Enabled by default by any @option{-O} option
 except @option{-O0} and @option{-Og}.  Optimizations enabled by this option
 include:
 @itemize @bullet


Re: [patch][v2a] libgomp: Add interop types and routines to OpenMP's headers and module

2024-08-23 Thread Andre Vehreschild
Hi Tobias,

I just had a short look at your PR. Besides that it did not git-am for me (see
below), I have only one question (see also below). Please note, that I have
only user-level experience in OpenMP and can say nothing about completeness or
soundness of your PR. I hope that a first check on overall style motivates a
"pro" to have a more in-depth look.

So my "ok" is just for style and overall applicability.

Regards,
Andre

On Thu, 22 Aug 2024 09:14:58 +0200
Tobias Burnus  wrote:

> This is nearly identical to v2, except that I presumably used 'git add 
> testsuite' when intending to use 'git add -u testsuite' in a last-minute 
> change as it contained a bunch of unrelated test files …
> 
> The only other change besides removing unrelated files  is that for the 
> generic part of omp_get_interop_type_desc, the data types ('int' for 
> fr_id, vendor, device_num; const char*' for fr_name, vendor_name) are 
> now returned in target.c while the specific types (for device, 
> device_context, targetsync platform) will eventually be handled by the 
> plugin function.
> 
> Tobias
> 
> Am 21.08.24 um 20:27 schrieb Tobias Burnus:
> > Nearly identical to v1, except that I realized that OpenMP permits to 
> > call those functions also from target regions.
> >
> > Hence, those also got those functions, including a use of 
> > omp_irc_other to make clear why it will fail …
> >
> > In addition, two (nonhost) target-region test files were added.
> >
> > Comments, remarks, suggestions before I commit it?


Attachment: 

> libgomp: Add interop types and routines to OpenMP's headers and module

git am did not work for me (sorry for the German):
$ git am interop-1v2a.diff
Wende an: This commit adds OpenMP 5.1+'s interop enumeration, type and routine
/mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:839: indent 
with spaces.
 "const char*", /* fr_name */
/mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:840: indent 
with spaces.
 "int", /* vendor */
/mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:841: indent 
with spaces.
 "const char *",/* vendor_name */
/mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:842: indent 
with spaces.
 "int"};/* device_num */
/mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:1332: space 
before tab in indent.
"omp_interop_none"));  /* GCC implementation 
choice.  */
Warnung: 5 Zeilen fügen Whitespace-Fehler hinzu.
Schwerwiegend: Leerer Name in Identifikation (für <>) nicht erlaubt.

> diff --git a/libgomp/config/gcn/target.c b/libgomp/config/gcn/target.c
> index 9cafea4e2cc..e9141f20ef3 100644
> --- a/libgomp/config/gcn/target.c
> +++ b/libgomp/config/gcn/target.c
> @@ -185,3 +185,102 @@ GOMP_target_enter_exit_data (int device, size_t mapnum,



> +omp_intptr_t
> +omp_get_interop_int (const omp_interop_t interop,
> +  omp_interop_property_t property_id,
> +  omp_interop_rc_t *ret_code)
> +{
> +  if (property_id < omp_ipr_first || property_id >= 0)
> +*ret_code = omp_irc_out_of_range;
> +  else if (interop == omp_interop_none)
> +*ret_code = omp_irc_empty;
> +  else
> +*ret_code = omp_irc_other;
> +  return 0;

Do I get this correct, that omp_intptr_t is a pointer to an integer? Would it
not be more intuitive to return nullptr here?

> +}




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


[PATCH v3 00/10] fortran: Inline MINLOC/MAXLOC without DIM argument [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Hello,

this is the third version of the inline MINLOC/MAXLOC without DIM patchset
whose second version was posted before at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-August/660599.html

Compared to the previous version, it contains a change of wording of the
documentation in patch 10.  The rest is rebased on a recent master
without any other change (as announced by Harald, there was a minor
conflict for patch 4/10 as a result of Andre's corank patch).

I need a ack for the newly added option in patch 10.

This series of patches enable the generation of inline code for the MINLOC
and MAXLOC intrinsics, when the DIM argument is not present.  The
generated code is based on the inline implementation already generated in
the scalar case, that is when ARRAY has rank 1 and DIM is present.  The
code is extended by using several variables (one for each dimension) where
the scalar code used just one, and collecting the variables to an array
before returning.

The patches are split in a way that allows inlining in more and more cases
as controlled by the gfc_inline_intrinsic_p predicate which evolves with
the patches.  The last patch (10/10) adds a flag to control inlining
from the command line.

v2 -> v3 changes:

 - In patch 10/10, rework the documentation:
   Add a summary statement as first sentence of the new flag documentation.
   Reword the documentation of the flag limitations to omit the ambiguous
   "scalar" qualification of intrinsic function results.
   Incorporate the sentence suggested during review.

v1 -> v2 changes:

 - In patch 1/10, use intrinsic ieee_arithmetic module to get NAN values in
   tests.  This required to split the tests using ieee_arithmetic to
   a separate file in the ieee/ subdirectory.

 - Add patch 4/10 removing the frontend minmaxloc pass.

 - Add patch 10/10 adding -finline-intrinsics flag to control MINLOC/MAXLOC
   inlining from the command line.

Mikael Morin (10):
  fortran: Add tests covering inline MINLOC/MAXLOC without DIM [PR90608]
  fortran: Disable frontend passes for inlinable MINLOC/MAXLOC [PR90608]
  fortran: Inline MINLOC/MAXLOC with no DIM and ARRAY of rank 1
[PR90608]
  fortran: Remove MINLOC/MAXLOC frontend optimization
  fortran: Outline array bound check generation code
  fortran: Inline integral MINLOC/MAXLOC with no DIM and no MASK
[PR90608]
  fortran: Inline integral MINLOC/MAXLOC with no DIM and scalar MASK
[PR90608]
  fortran: Inline non-character MINLOC/MAXLOC with no DIM [PR90608]
  fortran: Continue MINLOC/MAXLOC second loop where the first stopped
[PR90608]
  fortran: Add -finline-intrinsics flag for MINLOC/MAXLOC [PR90608]

 gcc/flag-types.h  |  30 +
 gcc/fortran/frontend-passes.cc|  57 --
 gcc/fortran/invoke.texi   |  31 +
 gcc/fortran/lang.opt  |  27 +
 gcc/fortran/options.cc|  21 +-
 gcc/fortran/trans-array.cc| 382 +
 gcc/fortran/trans-intrinsic.cc| 489 ---
 .../gfortran.dg/ieee/maxloc_nan_1.f90 |  44 +
 .../gfortran.dg/ieee/minloc_nan_1.f90 |  44 +
 gcc/testsuite/gfortran.dg/maxloc_7.f90| 208 +
 gcc/testsuite/gfortran.dg/maxloc_bounds_4.f90 |   4 +-
 gcc/testsuite/gfortran.dg/maxloc_bounds_5.f90 |   4 +-
 gcc/testsuite/gfortran.dg/maxloc_bounds_6.f90 |   4 +-
 gcc/testsuite/gfortran.dg/maxloc_bounds_7.f90 |   4 +-
 .../gfortran.dg/maxloc_with_mask_1.f90| 373 +
 gcc/testsuite/gfortran.dg/minloc_8.f90| 208 +
 .../gfortran.dg/minloc_with_mask_1.f90| 372 +
 gcc/testsuite/gfortran.dg/minmaxloc_18.f90| 772 ++
 gcc/testsuite/gfortran.dg/minmaxloc_18a.f90   |  10 +
 gcc/testsuite/gfortran.dg/minmaxloc_18b.f90   |  10 +
 gcc/testsuite/gfortran.dg/minmaxloc_18c.f90   |  10 +
 gcc/testsuite/gfortran.dg/minmaxloc_18d.f90   |  10 +
 22 files changed, 2767 insertions(+), 347 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/ieee/maxloc_nan_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/ieee/minloc_nan_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/maxloc_7.f90
 create mode 100644 gcc/testsuite/gfortran.dg/maxloc_with_mask_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minloc_8.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minloc_with_mask_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18a.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18b.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18c.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18d.f90

-- 
2.43.0



[PATCH v3 02/10] fortran: Disable frontend passes for inlinable MINLOC/MAXLOC [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Disable rewriting of MINLOC/MAXLOC expressions for which inline code
generation is supported.  Update the gfc_inline_intrinsic_function_p
predicate (already existing) for that, with the current state of
MINLOC/MAXLOC inlining support, that is only the cases of a scalar
result and non-CHARACTER argument for now.

This change has no effect currently, as the MINLOC/MAXLOC front-end passes
only change expressions of rank 1, but the inlining control predicate
gfc_inline_intrinsic_function_p returns false for those.  However, later
changes will extend MINLOC/MAXLOC inline expansion support to array
expressions and update the inlining control predicate, and this will become
effective.

PR fortran/90608

gcc/fortran/ChangeLog:

* frontend-passes.cc (optimize_minmaxloc): Skip if we can generate
inline code for the unmodified expression.
* trans-intrinsic.cc (gfc_inline_intrinsic_function_p): Add
MINLOC and MAXLOC cases.
---
 gcc/fortran/frontend-passes.cc |  3 ++-
 gcc/fortran/trans-intrinsic.cc | 23 +++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index 104ccb1a4c1..f7f49eea617 100644
--- a/gcc/fortran/frontend-passes.cc
+++ b/gcc/fortran/frontend-passes.cc
@@ -2281,7 +2281,8 @@ optimize_minmaxloc (gfc_expr **e)
   || fn->value.function.actual == NULL
   || fn->value.function.actual->expr == NULL
   || fn->value.function.actual->expr->ts.type == BT_CHARACTER
-  || fn->value.function.actual->expr->rank != 1)
+  || fn->value.function.actual->expr->rank != 1
+  || gfc_inline_intrinsic_function_p (fn))
 return;
 
   *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 0632e3e4d2f..cf5c8e63a9f 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -11662,6 +11662,29 @@ gfc_inline_intrinsic_function_p (gfc_expr *expr)
 case GFC_ISYM_TRANSPOSE:
   return true;
 
+case GFC_ISYM_MINLOC:
+case GFC_ISYM_MAXLOC:
+  {
+   /* Disable inline expansion if code size matters.  */
+   if (optimize_size)
+ return false;
+
+   gfc_actual_arglist *array_arg = expr->value.function.actual;
+   gfc_actual_arglist *dim_arg = array_arg->next;
+
+   gfc_expr *array = array_arg->expr;
+   gfc_expr *dim = dim_arg->expr;
+
+   if (!(array->ts.type == BT_INTEGER
+ || array->ts.type == BT_REAL))
+ return false;
+
+   if (array->rank == 1 && dim != nullptr)
+ return true;
+
+   return false;
+  }
+
 default:
   return false;
 }
-- 
2.43.0



[PATCH v3 04/10] fortran: Remove MINLOC/MAXLOC frontend optimization

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Remove the frontend pass rewriting calls of MINLOC/MAXLOC without DIM to
calls with one-valued DIM enclosed in an array constructor.  This
transformation was circumventing the limitation of inline MINLOC/MAXLOC code
generation to scalar cases only, allowing inline code to be generated if
ARRAY had rank 1 and DIM was absent.  As MINLOC/MAXLOC has gained support of
inline code generation in that case, the limitation is no longer effective,
and the transformation no longer necessary.

gcc/fortran/ChangeLog:

* frontend-passes.cc (optimize_minmaxloc): Remove.
(optimize_expr): Remove dispatch to optimize_minmaxloc.
---
 gcc/fortran/frontend-passes.cc | 58 --
 1 file changed, 58 deletions(-)

diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index f7f49eea617..c7cb9d2a389 100644
--- a/gcc/fortran/frontend-passes.cc
+++ b/gcc/fortran/frontend-passes.cc
@@ -36,7 +36,6 @@ static bool optimize_op (gfc_expr *);
 static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
 static bool optimize_trim (gfc_expr *);
 static bool optimize_lexical_comparison (gfc_expr *);
-static void optimize_minmaxloc (gfc_expr **);
 static bool is_empty_string (gfc_expr *e);
 static void doloop_warn (gfc_namespace *);
 static int do_intent (gfc_expr **);
@@ -356,17 +355,6 @@ optimize_expr (gfc_expr **e, int *walk_subtrees 
ATTRIBUTE_UNUSED,
   if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
 gfc_simplify_expr (*e, 0);
 
-  if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
-switch ((*e)->value.function.isym->id)
-  {
-  case GFC_ISYM_MINLOC:
-  case GFC_ISYM_MAXLOC:
-   optimize_minmaxloc (e);
-   break;
-  default:
-   break;
-  }
-
   if (function_expr)
 count_arglist --;
 
@@ -2266,52 +2254,6 @@ optimize_trim (gfc_expr *e)
   return true;
 }
 
-/* Optimize minloc(b), where b is rank 1 array, into
-   (/ minloc(b, dim=1) /), and similarly for maxloc,
-   as the latter forms are expanded inline.  */
-
-static void
-optimize_minmaxloc (gfc_expr **e)
-{
-  gfc_expr *fn = *e;
-  gfc_actual_arglist *a;
-  char *name, *p;
-
-  if (fn->rank != 1
-  || fn->value.function.actual == NULL
-  || fn->value.function.actual->expr == NULL
-  || fn->value.function.actual->expr->ts.type == BT_CHARACTER
-  || fn->value.function.actual->expr->rank != 1
-  || gfc_inline_intrinsic_function_p (fn))
-return;
-
-  *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
-  (*e)->shape = fn->shape;
-  fn->rank = 0;
-  fn->corank = 0;
-  fn->shape = NULL;
-  gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
-
-  name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
-  strcpy (name, fn->value.function.name);
-  p = strstr (name, "loc0");
-  p[3] = '1';
-  fn->value.function.name = gfc_get_string ("%s", name);
-  if (fn->value.function.actual->next)
-{
-  a = fn->value.function.actual->next;
-  gcc_assert (a->expr == NULL);
-}
-  else
-{
-  a = gfc_get_actual_arglist ();
-  fn->value.function.actual->next = a;
-}
-  a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
-  &fn->where);
-  mpz_set_ui (a->expr->value.integer, 1);
-}
-
 /* Data package to hand down for DO loop checks in a contained
procedure.  */
 typedef struct contained_info
-- 
2.43.0



[PATCH v3 08/10] fortran: Inline non-character MINLOC/MAXLOC with no DIM [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Enable generation of inline MINLOC/MAXLOC code in the case where DIM
is not present, and either ARRAY is of floating point type or MASK is an
array.  Those cases are the remaining bits to fully support inlining of
non-CHARACTER MINLOC/MAXLOC without DIM.  They are treated together because
they generate similar code, the NANs for REAL types being handled a bit like
a second level of masking.  These are the cases for which we generate two
sets of loops.

This change affects the code generating the second loop, that was previously
accessible only in the cases ARRAY has rank 1 only.  The single variable
initialization and update are changed to apply to multiple variables, one
per dimension.

The code generated is as follows (if ARRAY has rank 2):

for (idx11 in lower1..upper1)
  {
for (idx12 in lower2..upper2)
  {
...
if (...)
  {
...
goto second_loop;
  }
  }
  }
second_loop:
for (idx21 in lower1..upper1)
  {
for (idx22 in lower2..upper2)
  {
...
  }
  }

This code leads to processing the first elements redundantly, both in the
first set of loops and in the second one.  The loop over idx22 could
start from idx12 the first time it is run, but as it has to start from
lower2 for the rest of the runs, this change uses the same bounds for both
set of loops for simplicity.  In the rank 1 case, this makes the generated
code worse compared to the inline code that was generated before.  A later
change will introduce conditionals to avoid the duplicate processing and
restore the generated code in that case.

PR fortran/90608

gcc/fortran/ChangeLog:

* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Initialize
and update all the variables.  Put the label and goto in the
outermost scalarizer loop.  Don't start the second loop where the
first stopped.
(gfc_inline_intrinsic_function_p): Also return TRUE for array MASK
or for any REAL type.

gcc/testsuite/ChangeLog:

* gfortran.dg/maxloc_bounds_5.f90: Additionally accept error
messages reported by the scalarizer.
* gfortran.dg/maxloc_bounds_6.f90: Ditto.
---
 gcc/fortran/trans-intrinsic.cc| 127 --
 gcc/testsuite/gfortran.dg/maxloc_bounds_5.f90 |   4 +-
 gcc/testsuite/gfortran.dg/maxloc_bounds_6.f90 |   4 +-
 3 files changed, 87 insertions(+), 48 deletions(-)

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 45f5a7b6977..3d29bcaf590 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5361,12 +5361,55 @@ strip_kind_from_actual (gfc_actual_arglist * actual)
   }
   S++;
 }
-   B: ARRAY has rank 1, and DIM is absent.  Use the same code as the scalar
-  case and wrap the result in an array.
-   C: ARRAY has rank > 1, NANs are not supported, and DIM and MASK are absent.
-  Generate code similar to the single loop scalar case, but using one
-  variable per dimension, for example if ARRAY has rank 2:
-  4) NAN's aren't supported, no MASK:
+   B: Array result, non-CHARACTER type, DIM absent
+  Generate similar code as in the scalar case, using a collection of
+  variables (one per dimension) instead of a single variable as result.
+  Picking only cases 1) and 4) with ARRAY of rank 2, the generated code
+  becomes:
+  1) Array mask is used and NaNs need to be supported:
+limit = Infinity;
+pos0 = 0;
+pos1 = 0;
+S1 = from1;
+while (S1 <= to1) {
+  S0 = from0;
+  while (s0 <= to0 {
+if (mask[S1][S0]) {
+  if (pos0 == 0) {
+pos0 = S0 + (1 - from0);
+pos1 = S1 + (1 - from1);
+  }
+  if (a[S1][S0] <= limit) {
+limit = a[S1][S0];
+pos0 = S0 + (1 - from0);
+pos1 = S1 + (1 - from1);
+goto lab1;
+  }
+}
+S0++;
+  }
+  S1++;
+}
+goto lab2;
+lab1:;
+S1 = from1;
+while (S1 <= to1) {
+  S0 = from0;
+  while (S0 <= to0) {
+if (mask[S1][S0])
+  if (a[S1][S0] < limit) {
+limit = a[S1][S0];
+pos0 = S + (1 - from0);
+pos1 = S + (1 - from1);
+  }
+S0++;
+  }
+  S1++;
+}
+lab2:;
+result = { pos0, pos1 };
+  ...
+  4) NANs aren't supported, no array mask.
 limit = infinities_supported ? Infinity : huge (limit);
 pos0 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
 pos1 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
@@ -5384,7 +5427,7 @@ strip_kin

[PATCH v3 03/10] fortran: Inline MINLOC/MAXLOC with no DIM and ARRAY of rank 1 [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Enable inline code generation for the MINLOC and MAXLOC intrinsic, if the
DIM argument is not present and ARRAY has rank 1.  This case is similar to
the case where the result is scalar (DIM present and rank 1 ARRAY), which
already supports inline expansion of the intrinsic.  Both cases return
the same value, with the difference that the result is an array of size 1 if
DIM is absent, whereas it's a scalar if DIM  is present.  So all there is
to do for the new case to work is hook the inline expansion with the
scalarizer.

PR fortran/90608

gcc/fortran/ChangeLog:

* trans-array.cc (gfc_conv_ss_startstride): Set the scalarization
rank based on the MINLOC/MAXLOC rank if needed.  Call the inline
code generation and setup the scalarizer array descriptor info
in the MINLOC and MAXLOC cases.
* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Return the
result array element if the scalarizer is setup and we are inside
the loops.  Restrict library function call dispatch to the case
where inline expansion is not supported.  Declare an array result
if the expression isn't scalar.  Initialize the array result single
element and return the result variable if the expression isn't
scalar.
(walk_inline_intrinsic_minmaxloc): New function.
(walk_inline_intrinsic_function): Add MINLOC and MAXLOC cases,
dispatching to walk_inline_intrinsic_minmaxloc.
(gfc_add_intrinsic_ss_code): Add MINLOC and MAXLOC cases.
(gfc_inline_intrinsic_function_p): Return true if ARRAY has rank 1,
regardless of DIM.
---
 gcc/fortran/trans-array.cc |  25 
 gcc/fortran/trans-intrinsic.cc | 224 +++--
 2 files changed, 181 insertions(+), 68 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index ea5fff2e0c2..3c4831b6089 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4851,6 +4851,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
case GFC_ISYM_UBOUND:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UCOBOUND:
+   case GFC_ISYM_MAXLOC:
+   case GFC_ISYM_MINLOC:
case GFC_ISYM_SHAPE:
case GFC_ISYM_THIS_IMAGE:
  loop->dimen = ss->dimen;
@@ -4900,6 +4902,29 @@ done:
case GFC_SS_INTRINSIC:
  switch (expr->value.function.isym->id)
{
+   case GFC_ISYM_MINLOC:
+   case GFC_ISYM_MAXLOC:
+ {
+   gfc_se se;
+   gfc_init_se (&se, nullptr);
+   se.loop = loop;
+   se.ss = ss;
+   gfc_conv_intrinsic_function (&se, expr);
+   gfc_add_block_to_block (&outer_loop->pre, &se.pre);
+   gfc_add_block_to_block (&outer_loop->post, &se.post);
+
+   info->descriptor = se.expr;
+
+   info->data = gfc_conv_array_data (info->descriptor);
+   info->data = gfc_evaluate_now (info->data, &outer_loop->pre);
+
+   info->offset = gfc_index_zero_node;
+   info->start[0] = gfc_index_zero_node;
+   info->end[0] = gfc_index_zero_node;
+   info->stride[0] = gfc_index_one_node;
+   continue;
+ }
+
/* Fall through to supply start and stride.  */
case GFC_ISYM_LBOUND:
case GFC_ISYM_UBOUND:
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index cf5c8e63a9f..695c3591837 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5276,66 +5276,95 @@ strip_kind_from_actual (gfc_actual_arglist * actual)
we need to handle.  For performance reasons we sometimes create two
loops instead of one, where the second one is much simpler.
Examples for minloc intrinsic:
-   1) Result is an array, a call is generated
-   2) Array mask is used and NaNs need to be supported:
-  limit = Infinity;
-  pos = 0;
-  S = from;
-  while (S <= to) {
-   if (mask[S]) {
- if (pos == 0) pos = S + (1 - from);
- if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
-   }
-   S++;
-  }
-  goto lab2;
-  lab1:;
-  while (S <= to) {
-   if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
-   S++;
-  }
-  lab2:;
-   3) NaNs need to be supported, but it is known at compile time or cheaply
-  at runtime whether array is nonempty or not:
-  limit = Infinity;
-  pos = 0;
-  S = from;
-  while (S <= to) {
-   if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
-   S++;
-  }
-  if (from <= to) pos = 1;
-  goto lab2;
-  lab1:;
-  while (S <= to) {
-   if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
-   S++;
-  }
-  lab2:;
-   4) NaNs aren't supported, array mask is

[PATCH v3 06/10] fortran: Inline integral MINLOC/MAXLOC with no DIM and no MASK [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Enable generation of inline code for the MINLOC and MAXLOC intrinsic,
if the ARRAY argument is of integral type and of any rank (only the rank 1
case was previously inlined), and neither DIM nor MASK arguments are
present.

This needs a few adjustments in gfc_conv_intrinsic_minmaxloc,
mainly to replace the single variables POS and OFFSET, with collections
of variables, one variable per dimension each.

The restriction to integral ARRAY and absent MASK limits the scope of
the change to the cases where we generate single loop inline code.  The
code generation for the second loop is only accessible with ARRAY of rank
1, so it can continue using a single variable.  A later change will extend
inlining to the double loop cases.

There is some bounds checking code that was previously handled by the
library, and that needed some changes in the scalarizer to avoid regressing.
The bounds check code generation was already supported by the scalarizer,
but it was only applying to array reference sections, checking both
for array bound violation and for shape conformability between all the
involved arrays.  With this change, for MINLOC or MAXLOC, enable the
conformability check between all the scalarized arrays, and disable the
array bound violation check.

PR fortran/90608

gcc/fortran/ChangeLog:

* trans-array.cc (gfc_conv_ss_startstride): Set the MINLOC/MAXLOC
result upper bound using the rank of the ARRAY argument.  Ajdust
the error message for intrinsic result arrays.  Only check array
bounds for array references.  Move bound check decision code...
(bounds_check_needed): ... here as a new predicate.  Allow bound
check for MINLOC/MAXLOC intrinsic results.
* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Change the
result array upper bound to the rank of ARRAY.  Update the NONEMPTY
variable to depend on the non-empty extent of every dimension.  Use
one variable per dimension instead of a single variable for the
position and the offset.  Update their declaration, initialization,
and update to affect the variable of each dimension.  Use the first
variable only in areas only accessed with rank 1 ARRAY argument.
Set every element of the result using its corresponding variable.
(gfc_inline_intrinsic_function_p): Return true for integral ARRAY
and absent DIM and MASK.

gcc/testsuite/ChangeLog:

* gfortran.dg/maxloc_bounds_4.f90: Additionally accept the error
message emitted by the scalarizer.
---
 gcc/fortran/trans-array.cc|  70 ++--
 gcc/fortran/trans-intrinsic.cc| 150 +-
 gcc/testsuite/gfortran.dg/maxloc_bounds_4.f90 |   4 +-
 3 files changed, 166 insertions(+), 58 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index bc5f5900c6a..bb694371b47 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4956,6 +4956,35 @@ add_check_section_in_array_bounds (stmtblock_t *inner, 
gfc_ss_info *ss_info,
 }
 
 
+/* Tells whether we need to generate bounds checking code for the array
+   associated with SS.  */
+
+bool
+bounds_check_needed (gfc_ss *ss)
+{
+  /* Catch allocatable lhs in f2003.  */
+  if (flag_realloc_lhs && ss->no_bounds_check)
+return false;
+
+  gfc_ss_info *ss_info = ss->info;
+  if (ss_info->type == GFC_SS_SECTION)
+return true;
+
+  if (!(ss_info->type == GFC_SS_INTRINSIC
+   && ss_info->expr
+   && ss_info->expr->expr_type == EXPR_FUNCTION))
+return false;
+
+  gfc_intrinsic_sym *isym = ss_info->expr->value.function.isym;
+  if (!(isym
+   && (isym->id == GFC_ISYM_MAXLOC
+   || isym->id == GFC_ISYM_MINLOC)))
+return false;
+
+  return gfc_inline_intrinsic_function_p (ss_info->expr);
+}
+
+
 /* Calculates the range start and stride for a SS chain.  Also gets the
descriptor and data pointer.  The range of vector subscripts is the size
of the vector.  Array bounds are also checked.  */
@@ -5057,10 +5086,17 @@ done:
info->data = gfc_conv_array_data (info->descriptor);
info->data = gfc_evaluate_now (info->data, &outer_loop->pre);
 
-   info->offset = gfc_index_zero_node;
+   gfc_expr *array = expr->value.function.actual->expr;
+   tree rank = build_int_cst (gfc_array_index_type, array->rank);
+
+   tree tmp = fold_build2_loc (input_location, MINUS_EXPR,
+   gfc_array_index_type, rank,
+   gfc_index_one_node);
+
+   info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
info->start[0] = gfc_index_zero_node;
-   info->end[0] = gfc_index_zero_node;
info->stride[0] = gfc_index_one_node;
+   info->offset = gfc_index_zero_node;
continue;
  }
 

[PATCH v3 07/10] fortran: Inline integral MINLOC/MAXLOC with no DIM and scalar MASK [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Enable the generation of inline code for MINLOC/MAXLOC when argument ARRAY
is of integral type, DIM is not present, and MASK is present and is scalar
(only absent MASK or rank 1 ARRAY were inlined before).

Scalar masks are implemented with a wrapping condition around the code one
would generate if MASK wasn't present, so they are easy to support once
inline code without MASK is working.

PR fortran/90608

gcc/fortran/ChangeLog:

* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Generate
variable initialization for each dimension in the else branch of
the toplevel condition.
(gfc_inline_intrinsic_function_p): Return TRUE for scalar MASK.

gcc/testsuite/ChangeLog:

* gfortran.dg/maxloc_bounds_7.f90: Additionally accept the error message
reported by the scalarizer.
---
 gcc/fortran/trans-intrinsic.cc| 13 -
 gcc/testsuite/gfortran.dg/maxloc_bounds_7.f90 |  4 ++--
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 1215cd89630..45f5a7b6977 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5917,7 +5917,6 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
   /* For a scalar mask, enclose the loop in an if statement.  */
   if (maskexpr && maskss == NULL)
 {
-  gcc_assert (loop.dimen == 1);
   tree ifmask;
 
   gfc_init_se (&maskse, NULL);
@@ -5932,7 +5931,8 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
 the pos variable the same way as above.  */
 
   gfc_init_block (&elseblock);
-  gfc_add_modify (&elseblock, pos[0], gfc_index_zero_node);
+  for (int i = 0; i < loop.dimen; i++)
+   gfc_add_modify (&elseblock, pos[i], gfc_index_zero_node);
   elsetmp = gfc_finish_block (&elseblock);
   ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp);
@@ -11833,9 +11833,12 @@ gfc_inline_intrinsic_function_p (gfc_expr *expr)
if (array->rank == 1)
  return true;
 
-   if (array->ts.type == BT_INTEGER
-   && dim == nullptr
-   && mask == nullptr)
+   if (array->ts.type != BT_INTEGER
+   || dim != nullptr)
+ return false;
+
+   if (mask == nullptr
+   || mask->rank == 0)
  return true;
 
return false;
diff --git a/gcc/testsuite/gfortran.dg/maxloc_bounds_7.f90 
b/gcc/testsuite/gfortran.dg/maxloc_bounds_7.f90
index 206a29b149d..3aa9d3dcebe 100644
--- a/gcc/testsuite/gfortran.dg/maxloc_bounds_7.f90
+++ b/gcc/testsuite/gfortran.dg/maxloc_bounds_7.f90
@@ -1,6 +1,6 @@
 ! { dg-do run }
 ! { dg-options "-fbounds-check" }
-! { dg-shouldfail "Incorrect extent in return value of MAXLOC intrinsic: is 3, 
should be 2" }
+! { dg-shouldfail "Incorrect extent in return value of MAXLOC intrinsic: is 3, 
should be 2|Array bound mismatch for dimension 1 of array 'res' .3/2." }
 module tst
 contains
   subroutine foo(res)
@@ -18,4 +18,4 @@ program main
   integer :: res(3)
   call foo(res)
 end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return value of 
MAXLOC intrinsic: is 3, should be 2" }
+! { dg-output "Fortran runtime error: Incorrect extent in return value of 
MAXLOC intrinsic: is 3, should be 2|Array bound mismatch for dimension 1 of 
array 'res' .3/2." }
-- 
2.43.0



[PATCH v3 01/10] fortran: Add tests covering inline MINLOC/MAXLOC without DIM [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Add the tests covering the various cases for which we are about to implement
inline expansion of MINLOC and MAXLOC.  Those are cases where the DIM
argument is not present.

PR fortran/90608

gcc/testsuite/ChangeLog:

* gfortran.dg/ieee/maxloc_nan_1.f90: New test.
* gfortran.dg/ieee/minloc_nan_1.f90: New test.
* gfortran.dg/maxloc_7.f90: New test.
* gfortran.dg/maxloc_with_mask_1.f90: New test.
* gfortran.dg/minloc_8.f90: New test.
* gfortran.dg/minloc_with_mask_1.f90: New test.
---
 .../gfortran.dg/ieee/maxloc_nan_1.f90 |  44 +++
 .../gfortran.dg/ieee/minloc_nan_1.f90 |  44 +++
 gcc/testsuite/gfortran.dg/maxloc_7.f90| 208 ++
 .../gfortran.dg/maxloc_with_mask_1.f90| 373 ++
 gcc/testsuite/gfortran.dg/minloc_8.f90| 208 ++
 .../gfortran.dg/minloc_with_mask_1.f90| 372 +
 6 files changed, 1249 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/ieee/maxloc_nan_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/ieee/minloc_nan_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/maxloc_7.f90
 create mode 100644 gcc/testsuite/gfortran.dg/maxloc_with_mask_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minloc_8.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minloc_with_mask_1.f90

diff --git a/gcc/testsuite/gfortran.dg/ieee/maxloc_nan_1.f90 
b/gcc/testsuite/gfortran.dg/ieee/maxloc_nan_1.f90
new file mode 100644
index 000..329b54e8e1f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ieee/maxloc_nan_1.f90
@@ -0,0 +1,44 @@
+! { dg-do run }
+!
+! PR fortran/90608
+! Check the correct behaviour of the inline MAXLOC implementation,
+! when ARRAY is filled with NANs.
+
+program p
+  implicit none
+  call check_without_mask
+  call check_with_mask
+contains
+  subroutine check_without_mask()
+use, intrinsic :: ieee_arithmetic
+real, allocatable :: a(:,:,:)
+real :: nan
+integer, allocatable :: m(:)
+if (.not. ieee_support_nan(nan)) return
+nan = ieee_value(nan, ieee_quiet_nan)
+allocate(a(3,3,3), source = nan)
+m = maxloc(a)
+if (size(m, dim=1) /= 3) stop 32
+if (any(m /= (/ 1, 1, 1 /))) stop 35
+  end subroutine
+  subroutine check_with_mask()
+use, intrinsic :: ieee_arithmetic
+real, allocatable :: a(:,:,:)
+logical, allocatable :: m(:,:,:)
+real :: nan
+integer, allocatable :: r(:)
+if (.not. ieee_support_nan(nan)) return
+nan = ieee_value(nan, ieee_quiet_nan)
+allocate(a(3,3,3), source = nan)
+allocate(m(3,3,3))
+m(:,:,:) = reshape((/ .false., .false., .true. , .true. , .false., &
+  .true. , .false., .false., .false., .true. , &
+  .true. , .false., .true. , .true. , .true. , &
+  .false., .false., .true. , .true. , .false., &
+  .false., .true. , .false., .false., .true. , &
+  .true. , .true. /), shape(m))
+r = maxloc(a, mask = m)
+if (size(r, dim = 1) /= 3) stop 62
+if (any(r /= (/ 3, 1, 1 /))) stop 65
+  end subroutine
+end program p
diff --git a/gcc/testsuite/gfortran.dg/ieee/minloc_nan_1.f90 
b/gcc/testsuite/gfortran.dg/ieee/minloc_nan_1.f90
new file mode 100644
index 000..8f71b4c4398
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ieee/minloc_nan_1.f90
@@ -0,0 +1,44 @@
+! { dg-do run }
+!
+! PR fortran/90608
+! Check the correct behaviour of the inline MINLOC implementation,
+! when ARRAY is filled with NANs.
+
+program p
+  implicit none
+  call check_without_mask
+  call check_with_mask
+contains
+  subroutine check_without_mask()
+use, intrinsic :: ieee_arithmetic
+real, allocatable :: a(:,:,:)
+real :: nan
+integer, allocatable :: m(:)
+if (.not. ieee_support_nan(nan)) return
+nan = ieee_value(nan, ieee_quiet_nan)
+allocate(a(3,3,3), source = nan)
+m = minloc(a)
+if (size(m, dim=1) /= 3) stop 32
+if (any(m /= (/ 1, 1, 1 /))) stop 35
+  end subroutine
+  subroutine check_with_mask()
+use, intrinsic :: ieee_arithmetic
+real, allocatable :: a(:,:,:)
+logical, allocatable :: m(:,:,:)
+real :: nan
+integer, allocatable :: r(:)
+if (.not. ieee_support_nan(nan)) return
+nan = ieee_value(nan, ieee_quiet_nan)
+allocate(a(3,3,3), source = nan)
+allocate(m(3,3,3))
+m(:,:,:) = reshape((/ .false., .false., .true. , .true. , .false., &
+  .true. , .false., .false., .false., .true. , &
+  .true. , .false., .true. , .true. , .true. , &
+  .false., .false., .true. , .true. , .false., &
+  .false., .true. , .false., .false., .true. , &
+  .true. , .true. /), shape(m))
+r = minloc(a, mask = m)
+if (size(r, dim = 1) /= 3) stop 62
+if (any(r /= (/ 3, 1, 1 /))) stop 65
+  end subroutine
+end program p
diff --git a/gcc

[PATCH v3 05/10] fortran: Outline array bound check generation code

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

The next patch will need reindenting of the array bound check generation
code.  This outlines it to its own function beforehand, reducing the churn
in the next patch.

-- >8 --

gcc/fortran/ChangeLog:

* trans-array.cc (gfc_conv_ss_startstride): Move array bound check
generation code...
(add_check_section_in_array_bounds): ... here as a new function.
---
 gcc/fortran/trans-array.cc | 297 ++---
 1 file changed, 143 insertions(+), 154 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 3c4831b6089..bc5f5900c6a 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4816,6 +4816,146 @@ gfc_conv_section_startstride (stmtblock_t * block, 
gfc_ss * ss, int dim)
 }
 
 
+/* Generate in INNER the bounds checking code along the dimension DIM for
+   the array associated with SS_INFO.  */
+
+static void
+add_check_section_in_array_bounds (stmtblock_t *inner, gfc_ss_info *ss_info,
+  int dim)
+{
+  gfc_expr *expr = ss_info->expr;
+  locus *expr_loc = &expr->where;
+  const char *expr_name = expr->symtree->name;
+
+  gfc_array_info *info = &ss_info->data.array;
+
+  bool check_upper;
+  if (dim == info->ref->u.ar.dimen - 1
+  && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
+check_upper = false;
+  else
+check_upper = true;
+
+  /* Zero stride is not allowed.  */
+  tree tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+ info->stride[dim], gfc_index_zero_node);
+  char * msg = xasprintf ("Zero stride is not allowed, for dimension %d "
+ "of array '%s'", dim + 1, expr_name);
+  gfc_trans_runtime_check (true, false, tmp, inner, expr_loc, msg);
+  free (msg);
+
+  tree desc = info->descriptor;
+
+  /* This is the run-time equivalent of resolve.cc's
+ check_dimension.  The logical is more readable there
+ than it is here, with all the trees.  */
+  tree lbound = gfc_conv_array_lbound (desc, dim);
+  tree end = info->end[dim];
+  tree ubound = check_upper ? gfc_conv_array_ubound (desc, dim) : NULL_TREE;
+
+  /* non_zerosized is true when the selected range is not
+ empty.  */
+  tree stride_pos = fold_build2_loc (input_location, GT_EXPR, 
logical_type_node,
+info->stride[dim], gfc_index_zero_node);
+  tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
+info->start[dim], end);
+  stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+   logical_type_node, stride_pos, tmp);
+
+  tree stride_neg = fold_build2_loc (input_location, LT_EXPR, 
logical_type_node,
+info->stride[dim], gfc_index_zero_node);
+  tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
+info->start[dim], end);
+  stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+   logical_type_node, stride_neg, tmp);
+  tree non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
+   logical_type_node, stride_pos,
+   stride_neg);
+
+  /* Check the start of the range against the lower and upper
+ bounds of the array, if the range is not empty.
+ If upper bound is present, include both bounds in the
+ error message.  */
+  if (check_upper)
+{
+  tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
+info->start[dim], lbound);
+  tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
+non_zerosized, tmp);
+  tree tmp2 = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
+  info->start[dim], ubound);
+  tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR, 
logical_type_node,
+ non_zerosized, tmp2);
+  msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' outside of "
+  "expected range (%%ld:%%ld)", dim + 1, expr_name);
+  gfc_trans_runtime_check (true, false, tmp, inner, expr_loc, msg,
+ fold_convert (long_integer_type_node, info->start[dim]),
+ fold_convert (long_integer_type_node, lbound),
+ fold_convert (long_integer_type_node, ubound));
+  gfc_trans_runtime_check (true, false, tmp2, inner, expr_loc, msg,
+ fold_convert (long_integer_type_node, info->start[dim]),
+ fold_convert (long_integer_type_node, lbound),
+ fold_convert (long_integer_type_node, ubound));
+  free (msg);
+}
+  else
+{
+  tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
+info->start[dim], lbound);
+  tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
+non_ze

[PATCH v3 09/10] fortran: Continue MINLOC/MAXLOC second loop where the first stopped [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

Continue the second set of loops where the first one stopped in the
generated inline MINLOC/MAXLOC code in the cases where the generated code
contains two sets of loops.  This fixes a regression that was introduced
when enabling the generation of inline MINLOC/MAXLOC code with ARRAY of rank
greater than 1, no DIM argument, and either non-scalar MASK or floating-
point ARRAY.

In the cases where two sets of loops are generated as inline MINLOC/MAXLOC
code, we previously generated code such as (for rank 2 ARRAY, so with two
levels of nesting):

for (idx11 in lower1..upper1)
  {
for (idx12 in lower2..upper2)
  {
...
if (...)
  {
...
goto second_loop;
  }
  }
  }
second_loop:
for (idx21 in lower1..upper1)
  {
for (idx22 in lower2..upper2)
  {
...
  }
  }

which means we process the first elements twice, once in the first set
of loops and once in the second one.  This change avoids this duplicate
processing by using a conditional as lower bound for the second set of
loops, generating code like:

second_loop_entry = false;
for (idx11 in lower1..upper1)
  {
for (idx12 in lower2..upper2)
  {
...
if (...)
  {
...
second_loop_entry = true;
goto second_loop;
  }
  }
  }
second_loop:
for (idx21 in (second_loop_entry ? idx11 : lower1)..upper1)
  {
for (idx22 in (second_loop_entry ? idx12 : lower2)..upper2)
  {
...
second_loop_entry = false;
  }
  }

It was expected that the compiler optimizations would be able to remove the
state variable second_loop_entry.  It is the case if ARRAY has rank 1 (so
without loop nesting), the variable is removed and the loop bounds become
unconditional, which restores previously generated code, fully fixing the
regression.  For larger rank, unfortunately, the state variable and
conditional loop bounds remain, but those cases were previously using
library calls, so it's not a regression.

PR fortran/90608

gcc/fortran/ChangeLog:

* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Generate a set
of index variables.  Set them using the loop indexes before leaving
the first set of loops.  Generate a new loop entry predicate.
Initialize it.  Set it before leaving the first set of loops.  Clear
it in the body of the second set of loops.  For the second set of
loops, update each loop lower bound to use the corresponding index
variable if the predicate variable is set.
---
 gcc/fortran/trans-intrinsic.cc | 33 +++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 3d29bcaf590..f490e795c02 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5371,6 +5371,7 @@ strip_kind_from_actual (gfc_actual_arglist * actual)
 pos0 = 0;
 pos1 = 0;
 S1 = from1;
+second_loop_entry = false;
 while (S1 <= to1) {
   S0 = from0;
   while (s0 <= to0 {
@@ -5383,6 +5384,7 @@ strip_kind_from_actual (gfc_actual_arglist * actual)
 limit = a[S1][S0];
 pos0 = S0 + (1 - from0);
 pos1 = S1 + (1 - from1);
+second_loop_entry = true;
 goto lab1;
   }
 }
@@ -5392,9 +5394,9 @@ strip_kind_from_actual (gfc_actual_arglist * actual)
 }
 goto lab2;
 lab1:;
-S1 = from1;
+S1 = second_loop_entry ? S1 : from1;
 while (S1 <= to1) {
-  S0 = from0;
+  S0 = second_loop_entry ? S0 : from0;
   while (S0 <= to0) {
 if (mask[S1][S0])
   if (a[S1][S0] < limit) {
@@ -5402,6 +5404,7 @@ strip_kind_from_actual (gfc_actual_arglist * actual)
 pos0 = S + (1 - from0);
 pos1 = S + (1 - from1);
   }
+second_loop_entry = false;
 S0++;
   }
   S1++;
@@ -5473,6 +5476,7 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
   gfc_expr *backexpr;
   gfc_se backse;
   tree pos[GFC_MAX_DIMENSIONS];
+  tree idx[GFC_MAX_DIMENSIONS];
   tree result_var = NULL_TREE;
   int n;
   bool optional_mask;
@@ -5554,6 +5558,8 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
   gfc_get_string ("pos%d", i));
   offset[i] = gfc_create_var (gfc_array_index_type,
  gfc_g

[PATCH v3 10/10] fortran: Add -finline-intrinsics flag for MINLOC/MAXLOC [PR90608]

2024-08-23 Thread Mikael Morin
From: Mikael Morin 

The documentation in this patch was partly reworded, compared
to the previous version posted at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-August/660607.html
The rest of the patch is unchanged, just rebased to a more recent
master.

Joseph is in CC as I need a ack for the new option.

Regression-tested on x86_64-pc-linux-gnu.
OK for master?

-- >8 --

Introduce the -finline-intrinsics flag to control from the command line
whether to generate either inline code or calls to the functions from the
library, for the MINLOC and MAXLOC intrinsics.

The flag allows to specify inlining either independently for each intrinsic
(either MINLOC or MAXLOC), or all together.  For each intrinsic, a default
value is set if none was set.  The default value depends on the optimization
setting: inlining is avoided if not optimizing or if optimizing for size;
otherwise inlining is preferred.

There is no direct support for this behaviour provided by the .opt options
framework.  It is obtained by defining three different variants of the flag
(finline-intrinsics, fno-inline-intrinsics, finline-intrinsics=) all using
the same underlying option variable.  Each enum value (corresponding to an
intrinsic function) uses two identical bits, and the variable is initialized
with alternated bits, so that we can tell whether the value was set or not
by checking whether the two bits have different values.

PR fortran/90608

gcc/ChangeLog:

* flag-types.h (enum gfc_inlineable_intrinsics): New type.

gcc/fortran/ChangeLog:

* invoke.texi(finline-intrinsics): Document new flag.
* lang.opt (finline-intrinsics, finline-intrinsics=,
fno-inline-intrinsics): New flags.
* options.cc (gfc_post_options): If the option variable controling
the inlining of MAXLOC (respectively MINLOC) has not been set, set
it or clear it depending on the optimization option variables.
* trans-intrinsic.cc (gfc_inline_intrinsic_function_p): Return false
if inlining for the intrinsic is disabled according to the option
variable.

gcc/testsuite/ChangeLog:

* gfortran.dg/minmaxloc_18.f90: New test.
* gfortran.dg/minmaxloc_18a.f90: New test.
* gfortran.dg/minmaxloc_18b.f90: New test.
* gfortran.dg/minmaxloc_18c.f90: New test.
* gfortran.dg/minmaxloc_18d.f90: New test.
---
 gcc/flag-types.h|  30 +
 gcc/fortran/invoke.texi |  31 +
 gcc/fortran/lang.opt|  27 +
 gcc/fortran/options.cc  |  21 +-
 gcc/fortran/trans-intrinsic.cc  |  13 +-
 gcc/testsuite/gfortran.dg/minmaxloc_18.f90  | 772 
 gcc/testsuite/gfortran.dg/minmaxloc_18a.f90 |  10 +
 gcc/testsuite/gfortran.dg/minmaxloc_18b.f90 |  10 +
 gcc/testsuite/gfortran.dg/minmaxloc_18c.f90 |  10 +
 gcc/testsuite/gfortran.dg/minmaxloc_18d.f90 |  10 +
 10 files changed, 929 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18a.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18b.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18c.f90
 create mode 100644 gcc/testsuite/gfortran.dg/minmaxloc_18d.f90

diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 1e497f0bb91..df56337f7e8 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -451,6 +451,36 @@ enum gfc_convert
 };
 
 
+/* gfortran -finline-intrinsics= values;
+   We use two identical bits for each value, and initialize with alternated
+   bits, so that we can check whether a value has been set by checking whether
+   the two bits have identical value.  */
+
+#define GFC_INL_INTR_VAL(idx) (3 << (2 * idx))
+#define GFC_INL_INTR_UNSET_VAL(val) (0x & (val))
+
+enum gfc_inlineable_intrinsics
+{
+  GFC_FLAG_INLINE_INTRINSIC_NONE = 0,
+  GFC_FLAG_INLINE_INTRINSIC_MAXLOC = GFC_INL_INTR_VAL (0),
+  GFC_FLAG_INLINE_INTRINSIC_MINLOC = GFC_INL_INTR_VAL (1),
+  GFC_FLAG_INLINE_INTRINSIC_ALL = GFC_FLAG_INLINE_INTRINSIC_MAXLOC
+ | GFC_FLAG_INLINE_INTRINSIC_MINLOC,
+
+  GFC_FLAG_INLINE_INTRINSIC_NONE_UNSET
+ = GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_NONE),
+  GFC_FLAG_INLINE_INTRINSIC_MAXLOC_UNSET
+ = GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_MAXLOC),
+  GFC_FLAG_INLINE_INTRINSIC_MINLOC_UNSET
+ = GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_MINLOC),
+  GFC_FLAG_INLINE_INTRINSIC_ALL_UNSET
+ = GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_ALL)
+};
+
+#undef GFC_INL_INTR_UNSET_VAL
+#undef GFC_INL_INTR_VAL
+
+
 /* Inline String Operations functions.  */
 enum ilsop_fn
 {
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 6bc42afe2c4..3d59728f433 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -194,6 +194,7 @@ and warnings}.
 -finit-character=

[Fortran, Patch, PR85002, v1] Fix deep-copy of alloc. comps. in coarrays ICEing and crashing w/ lib.

2024-08-23 Thread Andre Vehreschild
Hi all,

attached patch fixes an ICE during trans-phase when allocatable components in
derived typed coarrays were nested. I am nearly convinced, that the ICE is
mostly fixed by pr86468, because I get a slightly different ICE. Nevertheless
was the executable crashing with -fcoarray=lib because the deep copy was not
inserted in the coarray case, which is fixed by this patch now. Furthermore did
I correct a comment, that was describing the inverse of the code following.

Regtests ok on x86_64-pc-linux-gnu / Fedora 39. Ok for mainline?

Regards,
Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de
From db6ca3808956b6e7c6950cbf572f2bba0995e03e Mon Sep 17 00:00:00 2001
From: Andre Vehreschild 
Date: Fri, 23 Aug 2024 09:07:09 +0200
Subject: [PATCH] [Fortran] Fix deep copy allocatable components in coarrays.
 [PR85002]

Fix code for deep copy of allocatable components in derived type nested
structures generated, but not inserted when the copy had to be done in
a coarray.  Additionally fix a comment.

gcc/fortran/ChangeLog:

	PR fortran/85002
	* trans-array.cc (duplicate_allocatable_coarray): Allow adding
	of deep copy code in the when-allocated case.  Add bounds
	computation before condition, because coarrays need the bounds
	also when not allocated.
	(structure_alloc_comps): Duplication in the coarray case is done
	already, omit it.  Add the deep-code when duplication a coarray.
	* trans-expr.cc (gfc_trans_structure_assign): Fix comment.

gcc/testsuite/ChangeLog:

	* gfortran.dg/coarray/alloc_comp_9.f90: New test.
---
 gcc/fortran/trans-array.cc| 16 ++---
 gcc/fortran/trans-expr.cc |  2 +-
 .../gfortran.dg/coarray/alloc_comp_9.f90  | 23 +++
 3 files changed, 32 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/coarray/alloc_comp_9.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index ea5fff2e0c2..3472fc5b636 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -9505,10 +9505,9 @@ gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
 NULL_TREE, NULL_TREE);
 }

-
 static tree
-duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
-			   tree type, int rank)
+duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src, tree type,
+			   int rank, tree add_when_allocated)
 {
   tree tmp;
   tree size;
@@ -9562,7 +9561,7 @@ duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
   gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));

   if (rank)
-	nelems = gfc_full_array_size (&block, src, rank);
+	nelems = gfc_full_array_size (&globalblock, src, rank);
   else
 	nelems = integer_one_node;

@@ -9593,7 +9592,7 @@ duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
  fold_convert (size_type_node, size));
   gfc_add_expr_to_block (&block, tmp);
 }
-
+  gfc_add_expr_to_block (&block, add_when_allocated);
   tmp = gfc_finish_block (&block);

   /* Null the destination if the source is null; otherwise do
@@ -9772,7 +9771,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
 	 gfc_duplicate_allocatable (), where the deep copy code is just added
 	 into the if's body, by adding tmp (the deep copy code) as last
 	 argument to gfc_duplicate_allocatable ().  */
-  if (purpose == COPY_ALLOC_COMP
+  if (purpose == COPY_ALLOC_COMP && caf_mode == 0
 	  && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
 	tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
 	 tmp);
@@ -10502,8 +10501,9 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
 		 c->caf_token,
 		 NULL_TREE);
 		}
-		  tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
-		   ctype, rank);
+		  tmp
+		= duplicate_allocatable_coarray (dcmp, dst_tok, comp, ctype,
+		 rank, add_when_allocated);
 		}
 	  else
 		tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 4681a131139..4489490bb7d 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9692,7 +9692,7 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray)

   /* Register the component with the caf-lib before it is initialized.
 	 Register only allocatable components, that are not coarray'ed
-	 components (%comp[*]).  Only register when the constructor is not the
+	 components (%comp[*]).  Only register when the constructor is the
 	 null-expression.  */
   if (coarray && !cm->attr.codimension
 	  && (cm->attr.allocatable || cm->attr.pointer)
diff --git a/gcc/testsuite/gfortran.dg/coarray/alloc_comp_9.f90 b/gcc/testsuite/gfortran.dg/coarray/alloc_comp_9.f90
new file mode 100644
index 000..d8e739a07d8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/alloc_comp_9.f90
@@ -0,0 +1,23 @@
+!{ dg-do run }
+
+! C

Re: [patch][v2a] libgomp: Add interop types and routines to OpenMP's headers and module

2024-08-23 Thread Andre Vehreschild
Oh, and I get compile errors:

/mnt/work_store/gcc/gcc.test/libgomp/target.c: In function 
'omp_get_interop_type_desc':
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5179:30: error: excess elements 
in scalar initializer [-Werror]
 5179 |  "const char*", /* fr_name */
  |  ^
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5179:30: note: (near 
initialization for 'desc')
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5180:30: error: excess elements 
in scalar initializer [-Werror]
 5180 |  "int", /* vendor */
  |  ^
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5180:30: note: (near 
initialization for 'desc')
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5181:30: error: excess elements 
in scalar initializer [-Werror]
 5181 |  "const char *",/* vendor_name */
  |  ^~
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5181:30: note: (near 
initialization for 'desc')
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5182:30: error: excess elements 
in scalar initializer [-Werror]
 5182 |  "int"};/* device_num */
  |  ^
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5182:30: note: (near 
initialization for 'desc')
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5185:21: error: 'fr_id' 
undeclared (first use in this function)
 5185 |   if (property_id > fr_id || property_id < omp_ipr_first)
  | ^
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5185:21: note: each undeclared 
identifier is reported only once for each function it appears in
/mnt/work_store/gcc/gcc.test/libgomp/target.c:5188:16: error: returning 'char' 
from a function with return type 'const char *' makes pointer from integer 
without a cast [-Wint-conversion]
 5188 | return desc[omp_ipr_fr_id - property_id];
  |^

- Andre

On Fri, 23 Aug 2024 10:28:56 +0200
Andre Vehreschild  wrote:

> Hi Tobias,
> 
> I just had a short look at your PR. Besides that it did not git-am for me (see
> below), I have only one question (see also below). Please note, that I have
> only user-level experience in OpenMP and can say nothing about completeness or
> soundness of your PR. I hope that a first check on overall style motivates a
> "pro" to have a more in-depth look.
> 
> So my "ok" is just for style and overall applicability.
> 
> Regards,
>   Andre
> 
> On Thu, 22 Aug 2024 09:14:58 +0200
> Tobias Burnus  wrote:
> 
> > This is nearly identical to v2, except that I presumably used 'git add 
> > testsuite' when intending to use 'git add -u testsuite' in a last-minute 
> > change as it contained a bunch of unrelated test files …
> > 
> > The only other change besides removing unrelated files  is that for the 
> > generic part of omp_get_interop_type_desc, the data types ('int' for 
> > fr_id, vendor, device_num; const char*' for fr_name, vendor_name) are 
> > now returned in target.c while the specific types (for device, 
> > device_context, targetsync platform) will eventually be handled by the 
> > plugin function.
> > 
> > Tobias
> > 
> > Am 21.08.24 um 20:27 schrieb Tobias Burnus:  
> > > Nearly identical to v1, except that I realized that OpenMP permits to 
> > > call those functions also from target regions.
> > >
> > > Hence, those also got those functions, including a use of 
> > > omp_irc_other to make clear why it will fail …
> > >
> > > In addition, two (nonhost) target-region test files were added.
> > >
> > > Comments, remarks, suggestions before I commit it?  
> 
> 
> Attachment: 
> 
> > libgomp: Add interop types and routines to OpenMP's headers and module  
> 
> git am did not work for me (sorry for the German):
> $ git am interop-1v2a.diff
> Wende an: This commit adds OpenMP 5.1+'s interop enumeration, type and routine
> /mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:839:
> indent with spaces. "const char*", /* fr_name */
> /mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:840:
> indent with spaces. "int", /* vendor */
> /mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:841:
> indent with spaces. "const char *",/* vendor_name */
> /mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:842:
> indent with spaces. "int"};/* device_num */
> /mnt/work_store/gcc/gcc/.git/worktrees/gcc.test/rebase-apply/patch:1332:
> space before tab in indent. "omp_interop_none"));  /* GCC implementation
> choice.  */ Warnung: 5 Zeilen fügen Whitespace-Fehler hinzu.
> Schwerwiegend: Leerer Name in Identifikation (für <>) nicht erlaubt.
> 
> > diff --git a/libgomp/config/gcn/target.c b/libgomp/config/gcn/target.c
> > index 9cafea4e2cc..e9141f20ef3 100644
> > --- a/libgomp/config/gcn/target.c
> > +++ b/libgomp/co

Re: [patch][v3] libgomp: Add interop types and routines to OpenMP's headers and module

2024-08-23 Thread Tobias Burnus

v3:

Changes:

(A) The 'ret_code' arguments of omp_get_interop_{int,ptr,str} are 
actually 'optional'.


That's something that got lost in at some point between OpenMP 5.2 and 
TR13 (I filed OpenMP spec Issue #4165 for it). When adding it, I noticed 
that two '…_async' function lacked the '= NULL' for C++, permitting to 
omit the argument. — For my C and Fortran testcases, I added a test with 
NULL for C and omitted the argument for Fortran. I also changed the C 
code such that it also compiles with C++ and added a check that the 
omitted argument is handled correctly.


(B) Fixed a few libgomp/target.c issues, which sneaked in due to the wip 
patch for the libgomp plugin patch, posted at 
https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661207.html (among 
others, it also contained some spurious spaces).


Build and regtested on x86-64-gnu-linux (w/o offloading configured).

Any additional comments, suggestions, remarks?

Andre Vehreschild wrote:
[…]
First, Thanks for your comments. However, regarding:

+omp_intptr_t

Do I get this correct, that omp_intptr_t is a pointer to an integer?


No 'intptr_t' is a (signed) integer type which is has (at least) the 
size of a pointer; in Fortran, that's 'integer(c_intptr_t)'. And 
'omp_intptr_t' is just a typedef for 'intptr_t'. [BTW: I don't know why 
'intptr_t' was used and not, e.g., int64_t or just 'int'.]


Tobiaslibgomp: Add interop types and routines to OpenMP's headers and module

This commit adds OpenMP 5.1+'s interop enumeration, type and routine
declarations to the C/C++ header file and, new in OpenMP TR13, also to
the Fortran module and omp_lib.h header file.

While a stub implementation is provided, only with foreign runtime
support by the libgomp GPU plugins and with the 'interop' directive,
this becomes really useful.

libgomp/ChangeLog:

	* fortran.c (omp_get_interop_str_, omp_get_interop_name_,
	omp_get_interop_type_desc_, omp_get_interop_rc_desc_): Add.
	* libgomp.map (GOMP_5.1.3): New; add interop routines.
	* omp.h.in: Add interop typedefs, enum and prototypes.
	(__GOMP_DEFAULT_NULL): Define.
	(omp_target_memcpy_async, omp_target_memcpy_rect_async):
	Use it for the optional depend argument.
 	* omp_lib.f90.in: Add paramters and interfaces for interop.
	* omp_lib.h.in: Likewise; move F90 '&' to column 81 for
	-ffree-length-80.
	* target.c (omp_get_num_interop_properties, omp_get_interop_int,
	omp_get_interop_ptr, omp_get_interop_str, omp_get_interop_name,
	omp_get_interop_type_desc, omp_get_interop_rc_desc): Add.
	* config/gcn/target.c (omp_get_num_interop_properties,
	omp_get_interop_int, omp_get_interop_ptr, omp_get_interop_str,
	omp_get_interop_name, omp_get_interop_type_desc,
	omp_get_interop_rc_desc): Add.
	* config/nvptx/target.c (omp_get_num_interop_properties,
	omp_get_interop_int, omp_get_interop_ptr, omp_get_interop_str,
	omp_get_interop_name, omp_get_interop_type_desc,
	omp_get_interop_rc_desc): Add.
	* testsuite/libgomp.c-c++-common/interop-routines-1.c: New test.
	* testsuite/libgomp.c-c++-common/interop-routines-2.c: New test.
	* testsuite/libgomp.fortran/interop-routines-1.F90: New test.
	* testsuite/libgomp.fortran/interop-routines-2.F90: New test.
	* testsuite/libgomp.fortran/interop-routines-3.F: New test.
	* testsuite/libgomp.fortran/interop-routines-4.F: New test.
	* testsuite/libgomp.fortran/interop-routines-5.F: New test.
	* testsuite/libgomp.fortran/interop-routines-6.F: New test.
	* testsuite/libgomp.fortran/interop-routines-7.F90: New test.

 libgomp/config/gcn/target.c| 105 ++
 libgomp/config/nvptx/target.c  | 105 ++
 libgomp/fortran.c  |  41 +++
 libgomp/libgomp.map|  15 +
 libgomp/omp.h.in   |  78 -
 libgomp/omp_lib.f90.in |  99 ++
 libgomp/omp_lib.h.in   | 170 --
 libgomp/target.c   | 110 +++
 .../libgomp.c-c++-common/interop-routines-1.c  | 287 +
 .../libgomp.c-c++-common/interop-routines-2.c  | 354 +
 .../libgomp.fortran/interop-routines-1.F90 | 236 ++
 .../libgomp.fortran/interop-routines-2.F90 |   3 +
 .../testsuite/libgomp.fortran/interop-routines-3.F |   2 +
 .../testsuite/libgomp.fortran/interop-routines-4.F |   4 +
 .../testsuite/libgomp.fortran/interop-routines-5.F |   4 +
 .../testsuite/libgomp.fortran/interop-routines-6.F |   4 +
 .../libgomp.fortran/interop-routines-7.F90 | 290 +
 17 files changed, 1883 insertions(+), 24 deletions(-)

diff --git a/libgomp/config/gcn/target.c b/libgomp/config/gcn/target.c
index 9cafea4e2cc..f7fa6aa6396 100644
--- a/libgomp/config/gcn/target.c
+++ b/libgomp/config/gcn/target.c
@@ -185,3 +185,108 @@ GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
   (void) depend;
   __builtin_unreachable ();
 }
+
+

Fwd: [Bug fortran/116261] [15 regression] gfortran.dg/sizeof_6.f90 -O1 timeout since r15-2739-g4cb07a38233

2024-08-23 Thread Paul Richard Thomas
Hi All,

Since the patch for PR102689 was committed, sporadic time outs at -O1 have
been recorded and so I have reverted the patch.

This is a bit awkward because I have yet to see the problem. However, I
will endeavour to understand what went wrong.

Paul

-- Forwarded message -
From: pault at gcc dot gnu.org 
Date: Fri, 23 Aug 2024 at 14:14
Subject: [Bug fortran/116261] [15 regression] gfortran.dg/sizeof_6.f90 -O1
timeout since r15-2739-g4cb07a38233
To: 


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116261

Paul Thomas  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|NEW |RESOLVED

--- Comment #12 from Paul Thomas  ---
Reverted in commit r15-3123-gf9f599a44e3156a5f5679adc048ec6ff2f44cc0e

Closing as fixed

Paul