Re: [Patch, fortran] PR96087 - [12/13/14/15 Regression] ICE in gfc_get_symbol_decl, at fortran/trans-decl.c:1575

2025-01-22 Thread Andre Vehreschild
Hi Paul,

the patch looks reasonable to me. Ok for mainline.

Just a side-thought: Could it be possible, that the for-loop in trans-decl does
not find the result? Would an assert after the loop at least give a hint, where
something went wrong? That's just from reading the code, so if you think that
can not happen, feel free to commit w/o the assert.

Regards,
Andre

On Wed, 22 Jan 2025 14:03:15 +
Paul Richard Thomas  wrote:

> Hi All,
>
> This patch fixes a double ICE arising from confusion between the dummy
> symbol arising from a module function/subroutine interface and the module
> procedure itself. In both cases, use of the name is unambiguous, as
> explained in the ChangeLog. The testcase contains both the original and the
> variant in comment 1.
>
> Regtests OK with FC41/x86_64 - OK for mainline and later backporting?
>
> Paul
>
> Fortran: Regression- fix ICE at fortran/trans-decl.c:1575 [PR96087]
>
> 2025-01-22  Paul Thomas  
>
> gcc/fortran
> PR fortran/96087
> * trans-decl.cc (gfc_get_symbol_decl): If a dummy is missing a
> backend decl, it is likely that it has come from a module proc
> interface. Look for the formal symbol by name in the containing
> proc and use its backend decl.
> * trans-expr.cc (gfc_apply_interface_mapping_to_expr): For the
> same reason, match the name, rather than the symbol address to
> perform the mapping.
>
> gcc/testsuite/
> PR fortran/96087
> * gfortran.dg/pr96087.f90: New test.


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


[Patch, fortran] PR96087 - [12/13/14/15 Regression] ICE in gfc_get_symbol_decl, at fortran/trans-decl.c:1575

2025-01-22 Thread Paul Richard Thomas
Hi All,

This patch fixes a double ICE arising from confusion between the dummy
symbol arising from a module function/subroutine interface and the module
procedure itself. In both cases, use of the name is unambiguous, as
explained in the ChangeLog. The testcase contains both the original and the
variant in comment 1.

Regtests OK with FC41/x86_64 - OK for mainline and later backporting?

Paul

Fortran: Regression- fix ICE at fortran/trans-decl.c:1575 [PR96087]

2025-01-22  Paul Thomas  

gcc/fortran
PR fortran/96087
* trans-decl.cc (gfc_get_symbol_decl): If a dummy is missing a
backend decl, it is likely that it has come from a module proc
interface. Look for the formal symbol by name in the containing
proc and use its backend decl.
* trans-expr.cc (gfc_apply_interface_mapping_to_expr): For the
same reason, match the name, rather than the symbol address to
perform the mapping.

gcc/testsuite/
PR fortran/96087
* gfortran.dg/pr96087.f90: New test.
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 4ae22a5584d..97bb0a41858 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -1722,6 +1722,21 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 	sym->backend_decl = DECL_CHAIN (sym->backend_decl);
 	}
 
+  /* Automatic array indices in module procedures need the backend_decl
+	 to be extracted from the procedure formal arglist.  */
+  if (sym->attr.dummy && !sym->backend_decl)
+	{
+	  gfc_formal_arglist *f;
+	  for (f = sym->ns->proc_name->formal; f; f = f->next)
+	{
+	  gfc_symbol *fsym = f->sym;
+	  if (strcmp (sym->name, fsym->name))
+		continue;
+	  sym->backend_decl = fsym->backend_decl;
+	  break;
+	 }
+	}
+
   /* Dummy variables should already have been created.  */
   gcc_assert (sym->backend_decl);
 
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index bef49d32a58..1bf46c616bb 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -5099,7 +5099,7 @@ gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping,
   /* TODO Find out why the condition on expr->symtree had to be moved into
  the loop rather than being outside it, as originally.  */
   for (sym = mapping->syms; sym; sym = sym->next)
-if (expr->symtree && sym->old == expr->symtree->n.sym)
+if (expr->symtree && !strcmp (sym->old->name, expr->symtree->n.sym->name))
   {
 	if (sym->new_sym->n.sym->backend_decl)
 	  expr->symtree = sym->new_sym;
diff --git a/gcc/testsuite/gfortran.dg/pr96087.f90 b/gcc/testsuite/gfortran.dg/pr96087.f90
new file mode 100644
index 000..6c75d4f0cf2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr96087.f90
@@ -0,0 +1,46 @@
+! { dg-do run }
+
+module m
+   interface
+  module function f(a, n, b) result(z)
+ integer, intent(in) :: n
+ real :: z(n + 1)
+ real :: a, b
+  end
+   end interface
+contains
+   module procedure f
+  integer :: i
+  do i = 1, size(z)
+z(i) = real(i)
+  end do
+   end procedure
+end
+
+! Comment 1
+module n
+   interface
+  module subroutine g(n, z)
+ integer, intent(in) :: n
+ real :: z(n)
+  end
+   end interface
+contains
+   module procedure g
+  z = 1
+  if (int (sum (z)) /= n) stop 1
+   end procedure
+end
+
+  use m
+  use n
+  real, allocatable :: r(:)
+  integer :: i = 2
+  r = f (1.0, i+1, 2.0)
+  if (any (r .ne. [(real(i), i = 1,4)])) stop 2
+  if (any (f (3.0, 1, 4.0) .ne. [(real(i), i = 1,2)])) stop 3
+
+  r = [(real (i), i = 10,20)]
+  call g (5, r)
+  if (int (sum (r)) /= (sum ([(i, i = 15,20)]) + 5)) stop 4
+end


[PATCH] Fortran: do not evaluate arguments of MAXVAL/MINVAL too often [PR118613]

2025-01-22 Thread Harald Anlauf

Dear all,

while looking at details of a related but slightly different PR, I found
that we did evaluate the arguments to MINLOC/MAXLOC too often in the
inlined version.

The attached patch creates temporaries for array elements where needed,
and ensures that each array element is only touched once.  This required
a minor adjustment for the rank-1 algorithm, which is documented.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald

From d2a52256b3e4817e16a5d222c2fecd7bc66e5613 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Wed, 22 Jan 2025 22:44:39 +0100
Subject: [PATCH] Fortran: do not evaluate arguments of MAXVAL/MINVAL too often
 [PR118613]

	PR fortran/118613

gcc/fortran/ChangeLog:

	* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxval): Adjust algorithm
	for inlined version of MINLOC and MAXLOC so that arguments are only
	evaluted once, and create temporaries where necessary.  Document
	change of algorithm.

gcc/testsuite/ChangeLog:

	* gfortran.dg/maxval_arg_eval_count.f90: New test.
---
 gcc/fortran/trans-intrinsic.cc| 37 +++-
 .../gfortran.dg/maxval_arg_eval_count.f90 | 88 +++
 2 files changed, 121 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/maxval_arg_eval_count.f90

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index afbec5b2752..51237d0d3be 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -6409,8 +6409,16 @@ gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
   nonempty = false;
   S = from;
   while (S <= to) {
-	if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
-	S++;
+	if (mask[S]) {
+	  nonempty = true;
+	  if (a[S] <= limit) {
+	limit = a[S];
+	S++;
+	goto lab;
+	  }
+	else
+	  S++;
+	}
   }
   limit = nonempty ? NaN : huge (limit);
   lab:
@@ -6419,7 +6427,15 @@ gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
   at runtime whether array is nonempty or not, rank 1:
   limit = Infinity;
   S = from;
-  while (S <= to) { if (a[S] <= limit) goto lab; S++; }
+  while (S <= to) {
+	if (a[S] <= limit) {
+	  limit = a[S];
+	  S++;
+	  goto lab;
+	  }
+	else
+	  S++;
+  }
   limit = (from <= to) ? NaN : huge (limit);
   lab:
   while (S <= to) { limit = min (a[S], limit); S++; }
@@ -6710,6 +6726,7 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   arrayse.ss = arrayss;
   gfc_conv_expr_val (&arrayse, arrayexpr);
+  arrayse.expr = gfc_evaluate_now (arrayse.expr, &arrayse.pre);
   gfc_add_block_to_block (&block, &arrayse.pre);
 
   gfc_init_block (&block2);
@@ -6722,7 +6739,18 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
   tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
 			 logical_type_node, arrayse.expr, limit);
   if (lab)
-	ifbody = build1_v (GOTO_EXPR, lab);
+	{
+	  stmtblock_t ifblock;
+	  tree inc_loop;
+	  inc_loop = fold_build2_loc (input_location, PLUS_EXPR,
+  TREE_TYPE (loop.loopvar[0]),
+  loop.loopvar[0], gfc_index_one_node);
+	  gfc_init_block (&ifblock);
+	  gfc_add_modify (&ifblock, limit, arrayse.expr);
+	  gfc_add_modify (&ifblock, loop.loopvar[0], inc_loop);
+	  gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab));
+	  ifbody = gfc_finish_block (&ifblock);
+	}
   else
 	{
 	  stmtblock_t ifblock;
@@ -6816,6 +6844,7 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   arrayse.ss = arrayss;
   gfc_conv_expr_val (&arrayse, arrayexpr);
+  arrayse.expr = gfc_evaluate_now (arrayse.expr, &arrayse.pre);
   gfc_add_block_to_block (&block, &arrayse.pre);
 
   /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
diff --git a/gcc/testsuite/gfortran.dg/maxval_arg_eval_count.f90 b/gcc/testsuite/gfortran.dg/maxval_arg_eval_count.f90
new file mode 100644
index 000..1c1a04819a0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/maxval_arg_eval_count.f90
@@ -0,0 +1,88 @@
+! { dg-do run }
+!
+! PR fortran/118613 - check argument evaluation count of MAXVAL
+
+program p
+  implicit none
+  integer, parameter :: k = 2
+  integer :: n
+  integer :: i1(k*k), i2(k,k), mm
+  real:: a1(k*k), a2(k,k), mx
+  complex :: c1(k*k), c2(k,k)
+  logical :: m1(k*k), m2(k,k)
+
+  ! prepare mask for masked variants
+  m1 = .true.
+  m2 = .true.
+  i1 = 0
+  i2 = 0
+  a1 = 0.
+  a2 = 0.
+  c1 = 0.
+  c2 = 0.
+
+  ! integer
+  n = 0
+  mm = maxval (h(i1))
+  if (n /= k*k .or. mm /= 0) stop 1
+  n = 0
+  mm = maxval (h(i2))
+  if (n /= k*k .or. mm /= 0) stop 2
+  n = 0
+  mm = maxval (h(i1),m1)
+  if (n /= k*k .or. mm /= 0) stop 3
+  n = 0
+  mm = maxval (h(i2),m2)
+  if (n /= k*k .or. mm /= 0) stop 4
+
+  ! real
+  n = 0
+  mx = maxval (f(a1))
+  if (n /= k*k .or. mx /= 0) st

Re: [PATCH] Fortran: Added support for locality specs in DO CONCURRENT (Fortran 2018/23)

2025-01-22 Thread Damian Rouson
The first error message in my previous email led me to the following
constraint:

“*C1130*  A *variable-name *that appears in a LOCAL or LOCAL_INIT
*locality-spec *shall not have the ALLOCATABLE, INTENT (IN), or OPTIONAL
attribute, shall not be of finalizable type, shall not have an allocatable
ultimate component,...”

My first thought was, "Holy guacamole. That seems like such
a severe limitation that the feature seems almost useless."  Fortuitously,
however, it turns out that the code I sent a little while ago was missing
one important feature from my intended use case: associate.  As shown
below, using associate eliminates the first error, but I'm still confused
by the remaining error message.  Are locality specifiers actually supported
yet?

Damian

% cat locality.f90

program main

  implicit none

  integer pair

  integer :: mini_batch_size=1


  real, allocatable, dimension(:,:) :: a, dcdb



  allocate(a(1,1))

  allocate(dcdb(1,1))


  associate(a_ => a, dcdb_ => dcdb)

do concurrent (pair = 1:mini_batch_size) local(a_) reduce(+: dcdb_)

  a_ = 0.

  dcdb_ = 0.

end do

  end associate


end program


% gfortran locality.f90

*locality.f90:12:71:*


   12 | do concurrent (pair = 1:mini_batch_size) local(a_) reduce(+:
dcdb_)

  |
  *1*

*Error:* Sorry, LOCAL and LOCAL_INIT are not yet supported for ‘*do
concurrent*’ constructs at *(1)*


% gfortran --version

GNU Fortran (GCC) 15.0.1 20250119 (experimental)

Copyright (C) 2025 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Re: [PATCH] Fortran: Added support for locality specs in DO CONCURRENT (Fortran 2018/23)

2025-01-22 Thread Damian Rouson
I recently built the master branch of Iain's fork of gcc in order to test
the support for locality specifiers.   I have verified that the branch I
built contains the commit mentioned in this email thread
20b8500cfa522ebe0fcf756d5b32816da7f904dd.  The code below isn't designed to
do anything useful -- just to make sure the syntax works. Could someone
tell me why the second error message indicates that LOCAL is not supported
yet?  Also, the first error message is really interesting because if I'm
really not allowed to have anything allocatable inside LOCAL(), then I'm
going to have to go back to the drawing board regarding my intended use
case.  Any advice?

Damian

% cat locality.f90

program main

  implicit none

  integer pair

  integer :: mini_batch_size=1


  real, allocatable, dimension(:,:) :: a, dcdb



  allocate(a(1,1))

  allocate(dcdb(1,1))


  do concurrent (pair = 1:mini_batch_size) local(a) reduce(+: dcdb)

a = 0.

dcdb = 0.

  end do


end program


% gfortran locality.f90

*locality.f90:8:50:*


8 |   do concurrent (pair = 1:mini_batch_size) local(a) reduce(+: dcdb)

  |  *1*

*Error:* ALLOCATABLE attribute not permitted for ‘*a*’ in LOCAL
locality-spec at *(1)*

*locality.f90:8:67:*


8 |   do concurrent (pair = 1:mini_batch_size) local(a) reduce(+: dcdb)

  |
*1*

*Error:* Sorry, LOCAL and LOCAL_INIT are not yet supported for ‘*do
concurrent*’ constructs at *(1)*


gfortran --version

GNU Fortran (GCC) 15.0.1 20250119 (experimental)

Copyright (C) 2025 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.




On Mon, Jan 13, 2025 at 5:41 PM Jerry D  wrote:

> Committed as:
>
> commit 20b8500cfa522ebe0fcf756d5b32816da7f904dd (HEAD -> master,
> origin/master, origin/HEAD)
> Author: Anuj Mohite 
> Date:   Mon Jan 13 16:28:57 2025 -0800
>
>  Fortran: Add LOCALITY support for DO_CONCURRENT
>
>  This patch provided by Anuj Mohite as part of the GSoC
> project.
>  It is modified slightly by Jerry DeLisle for minor formatting.
>  The patch provides front-end parsing of the LOCALITY specs in
>  DO_CONCURRENT and adds numerous test cases.
>
>  gcc/fortran/ChangeLog:
>
>  * dump-parse-tree.cc (show_code_node):  Updated to use
>  c->ext.concur.forall_iterator instead of
> c->ext.forall_iterator.
>  * frontend-passes.cc (index_interchange): Updated to
>  use c->ext.concur.forall_iterator instead of
> c->ext.forall_iterator.
>  (gfc_code_walker): Likewise.
>  * gfortran.h (enum locality_type): Added new enum for
> locality types
>  in DO CONCURRENT constructs.
>  * match.cc (match_simple_forall): Updated to use
>  new_st.ext.concur.forall_iterator instead of
> new_st.ext.forall_iterator.
>  (gfc_match_forall): Likewise.
>  (gfc_match_do):  Implemented support for matching DO
> CONCURRENT locality
>  specifiers (LOCAL, LOCAL_INIT, SHARED, DEFAULT(NONE), and
> REDUCE).
>  * parse.cc (parse_do_block): Updated to use
>  new_st.ext.concur.forall_iterator instead of
> new_st.ext.forall_iterator.
>  * resolve.cc (struct check_default_none_data): Added struct
>  check_default_none_data.
>  (do_concur_locality_specs_f2023): New function to check
> compliance
>  with F2023's C1133 constraint for DO CONCURRENT.
>  (check_default_none_expr): New function to check DEFAULT(NONE)
>  compliance.
>  (resolve_locality_spec): New function to resolve locality
> specs.
>  (gfc_count_forall_iterators): Updated to use
>  code->ext.concur.forall_iterator.
>  (gfc_resolve_forall): Updated to use
> code->ext.concur.forall_iterator.
>  * st.cc (gfc_free_statement): Updated to free locality
> specifications
>  and use p->ext.concur.forall_iterator.
>  * trans-stmt.cc (gfc_trans_forall_1): Updated to use
>  code->ext.concur.forall_iterator.
>
>  gcc/testsuite/ChangeLog:
>
>  * gfortran.dg/do_concurrent_10.f90: New test.
>  * gfortran.dg/do_concurrent_8_f2018.f90: New test.
>  * gfortran.dg/do_concurrent_8_f2023.f90: New test.
>  * gfortran.dg/do_concurrent_9.f90: New test.
>  * gfortran.dg/do_concurrent_all_clauses.f90: New test.
>  * gfortran.dg/do_concurrent_basic.f90: New test.
>  * gfortran.dg/do_concurrent_constraints.f90: New test.
>  * gfortran.dg/do_concurrent_local_init.f90: New test.
>  * gfortran.dg/do_concurrent_locality_specs.f90: New test.
>  * gfortran.dg/do_concurrent_multiple_reduce.f90: New test.
>  

Re: [PATCH] Fortran: Added support for locality specs in DO CONCURRENT (Fortran 2018/23)

2025-01-22 Thread Andre Vehreschild
Hi Damian,

looking into the code I neither find the keyword LOCAL nor REDUCE. The match
routine also does not give any hint that those keywords are supported in a do
concurrent loop.

And here is the existing bug
ticket: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101602

But I don't see a ticket for REDUCE yet.

Sorry for the bad news.

Regards,
Andre

On Wed, 22 Jan 2025 20:59:02 -0800
Damian Rouson  wrote:

> The first error message in my previous email led me to the following
> constraint:
> 
> “*C1130*  A *variable-name *that appears in a LOCAL or LOCAL_INIT
> *locality-spec *shall not have the ALLOCATABLE, INTENT (IN), or OPTIONAL
> attribute, shall not be of finalizable type, shall not have an allocatable
> ultimate component,...”
> 
> My first thought was, "Holy guacamole. That seems like such
> a severe limitation that the feature seems almost useless."  Fortuitously,
> however, it turns out that the code I sent a little while ago was missing
> one important feature from my intended use case: associate.  As shown
> below, using associate eliminates the first error, but I'm still confused
> by the remaining error message.  Are locality specifiers actually supported
> yet?
> 
> Damian
> 
> % cat locality.f90
> 
> program main
> 
>   implicit none
> 
>   integer pair
> 
>   integer :: mini_batch_size=1
> 
> 
>   real, allocatable, dimension(:,:) :: a, dcdb
> 
> 
> 
>   allocate(a(1,1))
> 
>   allocate(dcdb(1,1))
> 
> 
>   associate(a_ => a, dcdb_ => dcdb)
> 
> do concurrent (pair = 1:mini_batch_size) local(a_) reduce(+: dcdb_)
> 
>   a_ = 0.
> 
>   dcdb_ = 0.
> 
> end do
> 
>   end associate
> 
> 
> end program
> 
> 
> % gfortran locality.f90
> 
> *locality.f90:12:71:*
> 
> 
>12 | do concurrent (pair = 1:mini_batch_size) local(a_) reduce(+:
> dcdb_)
> 
>   |
>   *1*
> 
> *Error:* Sorry, LOCAL and LOCAL_INIT are not yet supported for ‘*do
> concurrent*’ constructs at *(1)*
> 
> 
> % gfortran --version
> 
> GNU Fortran (GCC) 15.0.1 20250119 (experimental)
> 
> Copyright (C) 2025 Free Software Foundation, Inc.
> 
> This is free software; see the source for copying conditions.  There is NO
> 
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


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