public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896]
@ 2021-11-07 16:16 Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 1/5] fortran: Tiny sort_actual internal refactoring Mikael Morin
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Mikael Morin @ 2021-11-07 16:16 UTC (permalink / raw)
  To: fortran, gcc-patches


Hello,

This is the third submit of this patch series.
After submitting the v2 [2] for master, and a somewhat different variant for
backport [3], I thought it was defeating the purpose of the backporting
process.  So I have decided to rebase the master patches on the backport
patches, so that the backport patchs can get some testing on master first.

The problematic case is intrinsic procedures where an argument is actually
not used in the code generated (KIND argument of INDEX in the testcase),
which confuses the scalariser.

Thomas König comitted a change to workaround the problem, but it regressed
in PR97896.  These patches put the workaround where I think it is more
appropriate, namely at the beginning of the scalarisation procedure.
That’s what is done by the series [3] initially intended for backport only,
and now for master too.  This series is a followup to them.

What are left in this series are a couple of refactoring for the master
branch only.  They aim at being able to identify the KIND argument of the INDEX
intrinsic by its name, rather than counting the right number of next->next->next
indirections starting with the first argument.  It may seem overkill for just
this use case, but I think it’s worth having that facility in the long term.

Regression-tested on x86_64-linux-gnu.  Ok for master? 


Changes from v2 [2]:

  Rebase on the backport variant of the series.

Changes from v1 [1]:

  Use C structs and enums instead of C++ classes.


[1] https://gcc.gnu.org/pipermail/fortran/2021-August/056303.html
[2] https://gcc.gnu.org/pipermail/fortran/2021-August/056317.html
[3] https://gcc.gnu.org/pipermail/fortran/2021-August/056329.html


Mikael Morin (5):
  fortran: Tiny sort_actual internal refactoring
  fortran: Reverse actual vs dummy argument mapping
  fortran: simplify elemental arguments walking
  fortran: Delete redundant missing_arg_type field
  fortran: Identify arguments by their names

 gcc/fortran/gfortran.h        | 41 +++++++++++++++----
 gcc/fortran/interface.c       | 77 +++++++++++++++++++++++++++++++----
 gcc/fortran/intrinsic.c       | 53 ++++++++++++++++--------
 gcc/fortran/trans-array.c     | 35 +++++-----------
 gcc/fortran/trans-array.h     |  2 +-
 gcc/fortran/trans-expr.c      |  9 +++-
 gcc/fortran/trans-intrinsic.c |  2 +-
 gcc/fortran/trans-stmt.c      | 22 ----------
 gcc/fortran/trans.h           |  4 +-
 9 files changed, 161 insertions(+), 84 deletions(-)

-- 
2.33.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/5] fortran: Tiny sort_actual internal refactoring
  2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
@ 2021-11-07 16:16 ` Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 2/5] fortran: Reverse actual vs dummy argument mapping Mikael Morin
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mikael Morin @ 2021-11-07 16:16 UTC (permalink / raw)
  To: fortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 270 bytes --]


Preliminary refactoring to make further changes more obvious.
No functional change.

gcc/fortran/ChangeLog:
	* intrinsic.c (sort_actual): initialise variable and use it earlier.
---
 gcc/fortran/intrinsic.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-fortran-Tiny-sort_actual-internal-refactoring.patch --]
[-- Type: text/x-patch; name="0001-fortran-Tiny-sort_actual-internal-refactoring.patch", Size: 666 bytes --]

diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index a6a18a471e3..49ef3b2a3d2 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -4378,19 +4378,18 @@ do_sort:
 
   for (f = formal; f; f = f->next)
     {
-      if (f->actual && f->actual->label != NULL && f->ts.type)
+      a = f->actual;
+      if (a && a->label != NULL && f->ts.type)
 	{
 	  gfc_error ("ALTERNATE RETURN not permitted at %L", where);
 	  return false;
 	}
 
-      if (f->actual == NULL)
+      if (a == NULL)
 	{
 	  a = gfc_get_actual_arglist ();
 	  a->missing_arg_type = f->ts.type;
 	}
-      else
-	a = f->actual;
 
       if (actual == NULL)
 	*ap = a;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 2/5] fortran: Reverse actual vs dummy argument mapping
  2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 1/5] fortran: Tiny sort_actual internal refactoring Mikael Morin
@ 2021-11-07 16:16 ` Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 3/5] fortran: simplify elemental arguments walking Mikael Morin
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mikael Morin @ 2021-11-07 16:16 UTC (permalink / raw)
  To: fortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1776 bytes --]


There was originally no way from an actual argument to get
to the corresponding dummy argument, even if the job of sorting
and matching actual with dummy arguments was done.
The closest was a field named actual in gfc_intrinsic_arg that was
used as scratch data when sorting arguments of one specific call.
However that value was overwritten later on as arguments of another
call to the same procedure were sorted and matched.

This change removes that field from gfc_intrinsic_arg and adds instead
a new field associated_dummy in gfc_actual_arglist.

The new field has as type a new wrapper struct gfc_dummy_arg that provides
a common interface to both dummy arguments of user-defined procedures
(which have type gfc_formal_arglist) and dummy arguments of intrinsic procedures
(which have type gfc_intrinsic_arg).

As the removed field was used in the code sorting and matching arguments,
that code has to be updated.  Two local vectors with matching indices
are introduced for respectively dummy and actual arguments, and the
loops are modified to use indices and update those argument vectors.

gcc/fortran/ChangeLog:
	* gfortran.h (gfc_dummy_arg_kind, gfc_dummy_arg): New.
	(gfc_actual_arglist): New field associated_dummy.
	(gfc_intrinsic_arg): Remove field actual.
	* interface.c (get_nonintrinsic_dummy_arg): New.
	(gfc_compare_actual): Initialize associated_dummy.
	* intrinsic.c (get_intrinsic_dummy_arg): New.
	(sort_actual):  Add argument vectors.
	Use loops with indices on argument vectors.
	Initialize associated_dummy.
---
 gcc/fortran/gfortran.h  | 31 +++++++++++++++++++++++++++--
 gcc/fortran/interface.c | 21 ++++++++++++++++++--
 gcc/fortran/intrinsic.c | 43 ++++++++++++++++++++++++++++++-----------
 3 files changed, 80 insertions(+), 15 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-fortran-Reverse-actual-vs-dummy-argument-mapping.patch --]
[-- Type: text/x-patch; name="0002-fortran-Reverse-actual-vs-dummy-argument-mapping.patch", Size: 6379 bytes --]

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 8c11cf6d18d..d678c6b56dc 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1199,6 +1199,9 @@ gfc_formal_arglist;
 #define gfc_get_formal_arglist() XCNEW (gfc_formal_arglist)
 
 
+struct gfc_dummy_arg;
+
+
 /* The gfc_actual_arglist structure is for actual arguments and
    for type parameter specification lists.  */
 typedef struct gfc_actual_arglist
@@ -1215,6 +1218,11 @@ typedef struct gfc_actual_arglist
   gfc_param_spec_type spec_type;
 
   struct gfc_expr *expr;
+
+  /*  The dummy arg this actual arg is associated with, if the interface
+      is explicit.  NULL otherwise.  */
+  gfc_dummy_arg *associated_dummy;
+
   struct gfc_actual_arglist *next;
 }
 gfc_actual_arglist;
@@ -2298,14 +2306,33 @@ typedef struct gfc_intrinsic_arg
   gfc_typespec ts;
   unsigned optional:1, value:1;
   ENUM_BITFIELD (sym_intent) intent:2;
-  gfc_actual_arglist *actual;
 
   struct gfc_intrinsic_arg *next;
-
 }
 gfc_intrinsic_arg;
 
 
+typedef enum {
+  GFC_UNDEFINED_DUMMY_ARG = 0,
+  GFC_INTRINSIC_DUMMY_ARG,
+  GFC_NON_INTRINSIC_DUMMY_ARG
+}
+gfc_dummy_arg_intrinsicness;
+
+/* dummy arg of either an intrinsic or a user-defined procedure.  */
+struct gfc_dummy_arg
+{
+  gfc_dummy_arg_intrinsicness intrinsicness;
+
+  union {
+    gfc_intrinsic_arg *intrinsic;
+    gfc_formal_arglist *non_intrinsic;
+  } u;
+};
+
+#define gfc_get_dummy_arg() XCNEW (gfc_dummy_arg)
+
+
 /* Specifies the various kinds of check functions used to verify the
    argument lists of intrinsic functions. fX with X an integer refer
    to check functions of intrinsics with X arguments. f1m is used for
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 24698be8364..c4ec0d89a58 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -3043,6 +3043,18 @@ lookup_arg_fuzzy (const char *arg, gfc_formal_arglist *arguments)
 }
 
 
+static gfc_dummy_arg *
+get_nonintrinsic_dummy_arg (gfc_formal_arglist *formal)
+{
+  gfc_dummy_arg * const dummy_arg = gfc_get_dummy_arg ();
+
+  dummy_arg->intrinsicness = GFC_NON_INTRINSIC_DUMMY_ARG;
+  dummy_arg->u.non_intrinsic = formal;
+
+  return dummy_arg;
+}
+
+
 /* Given formal and actual argument lists, see if they are compatible.
    If they are compatible, the actual argument list is sorted to
    correspond with the formal list, and elements for missing optional
@@ -3150,6 +3162,8 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
 			   "call at %L", where);
 	  return false;
 	}
+      else
+	a->associated_dummy = get_nonintrinsic_dummy_arg (f);
 
       if (a->expr == NULL)
 	{
@@ -3646,9 +3660,12 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
   /* The argument lists are compatible.  We now relink a new actual
      argument list with null arguments in the right places.  The head
      of the list remains the head.  */
-  for (i = 0; i < n; i++)
+  for (f = formal, i = 0; f; f = f->next, i++)
     if (new_arg[i] == NULL)
-      new_arg[i] = gfc_get_actual_arglist ();
+      {
+	new_arg[i] = gfc_get_actual_arglist ();
+	new_arg[i]->associated_dummy = get_nonintrinsic_dummy_arg (f);
+      }
 
   if (na != 0)
     {
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 49ef3b2a3d2..f6d061a847c 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -4236,6 +4236,18 @@ remove_nullargs (gfc_actual_arglist **ap)
 }
 
 
+static gfc_dummy_arg *
+get_intrinsic_dummy_arg (gfc_intrinsic_arg *intrinsic)
+{
+  gfc_dummy_arg * const dummy_arg = gfc_get_dummy_arg ();
+
+  dummy_arg->intrinsicness = GFC_INTRINSIC_DUMMY_ARG;
+  dummy_arg->u.intrinsic = intrinsic;
+
+  return dummy_arg;
+}
+
+
 /* Given an actual arglist and a formal arglist, sort the actual
    arglist so that its arguments are in a one-to-one correspondence
    with the format arglist.  Arguments that are not present are given
@@ -4253,8 +4265,14 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
   remove_nullargs (ap);
   actual = *ap;
 
+  auto_vec<gfc_intrinsic_arg *> dummy_args;
+  auto_vec<gfc_actual_arglist *> ordered_actual_args;
+
   for (f = formal; f; f = f->next)
-    f->actual = NULL;
+    dummy_args.safe_push (f);
+
+  ordered_actual_args.safe_grow_cleared (dummy_args.length (),
+					 /* exact = */true);
 
   f = formal;
   a = actual;
@@ -4306,7 +4324,7 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
 	}
     }
 
-  for (;;)
+  for (int i = 0;; i++)
     {		/* Put the nonkeyword arguments in a 1:1 correspondence */
       if (f == NULL)
 	break;
@@ -4316,7 +4334,7 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
       if (a->name != NULL)
 	goto keywords;
 
-      f->actual = a;
+      ordered_actual_args[i] = a;
 
       f = f->next;
       a = a->next;
@@ -4334,7 +4352,8 @@ keywords:
      to be keyword arguments.  */
   for (; a; a = a->next)
     {
-      for (f = formal; f; f = f->next)
+      int idx;
+      FOR_EACH_VEC_ELT (dummy_args, idx, f)
 	if (strcmp (a->name, f->name) == 0)
 	  break;
 
@@ -4349,21 +4368,21 @@ keywords:
 	  return false;
 	}
 
-      if (f->actual != NULL)
+      if (ordered_actual_args[idx] != NULL)
 	{
 	  gfc_error ("Argument %qs appears twice in call to %qs at %L",
 		     f->name, name, where);
 	  return false;
 	}
-
-      f->actual = a;
+      ordered_actual_args[idx] = a;
     }
 
 optional:
   /* At this point, all unmatched formal args must be optional.  */
-  for (f = formal; f; f = f->next)
+  int idx;
+  FOR_EACH_VEC_ELT (dummy_args, idx, f)
     {
-      if (f->actual == NULL && f->optional == 0)
+      if (ordered_actual_args[idx] == NULL && f->optional == 0)
 	{
 	  gfc_error ("Missing actual argument %qs in call to %qs at %L",
 		     f->name, name, where);
@@ -4376,9 +4395,9 @@ do_sort:
      together in a way that corresponds with the formal list.  */
   actual = NULL;
 
-  for (f = formal; f; f = f->next)
+  FOR_EACH_VEC_ELT (dummy_args, idx, f)
     {
-      a = f->actual;
+      a = ordered_actual_args[idx];
       if (a && a->label != NULL && f->ts.type)
 	{
 	  gfc_error ("ALTERNATE RETURN not permitted at %L", where);
@@ -4391,6 +4410,8 @@ do_sort:
 	  a->missing_arg_type = f->ts.type;
 	}
 
+      a->associated_dummy = get_intrinsic_dummy_arg (f);
+
       if (actual == NULL)
 	*ap = a;
       else

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 3/5] fortran: simplify elemental arguments walking
  2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 1/5] fortran: Tiny sort_actual internal refactoring Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 2/5] fortran: Reverse actual vs dummy argument mapping Mikael Morin
@ 2021-11-07 16:16 ` Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 4/5] fortran: Delete redundant missing_arg_type field Mikael Morin
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mikael Morin @ 2021-11-07 16:16 UTC (permalink / raw)
  To: fortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1611 bytes --]


This adds two functions working with the wrapper struct gfc_dummy_arg
and makes usage of them to simplify a bit the walking of elemental
procedure arguments for scalarization.  As information about dummy arguments
can be obtained from the actual argument through the just-introduced
associated_dummy field, there is no need to carry around the procedure
interface and walk dummy arguments manually together with actual arguments.

gcc/fortran/ChangeLog:
	* interface.c (gfc_dummy_arg_get_typespec,
	gfc_dummy_arg_is_optional): New functions.
	* gfortran.h (gfc_dummy_arg_get_typespec,
	gfc_dummy_arg_is_optional): Declare them.
	* trans.h (gfc_ss_info::dummy_arg): Use the wrapper type
	as declaration type.
	* trans-array.c (gfc_scalar_elemental_arg_saved_as_reference):
	use gfc_dummy_arg_get_typespec function to get the type.
	(gfc_walk_elemental_function_args): Remove proc_ifc argument.
	Get info about the dummy arg using the associated_dummy field.
	* trans-array.h (gfc_walk_elemental_function_args): Update declaration.
	* trans-intrinsic.c (gfc_walk_intrinsic_function):
	Update call to gfc_walk_elemental_function_args.
	* trans-stmt.c (gfc_trans_call): Ditto.
	(get_proc_ifc_for_call): Remove.
---
 gcc/fortran/gfortran.h        |  4 ++++
 gcc/fortran/interface.c       | 34 ++++++++++++++++++++++++++++++++++
 gcc/fortran/trans-array.c     | 19 ++++++-------------
 gcc/fortran/trans-array.h     |  2 +-
 gcc/fortran/trans-intrinsic.c |  2 +-
 gcc/fortran/trans-stmt.c      | 22 ----------------------
 gcc/fortran/trans.h           |  4 ++--
 7 files changed, 48 insertions(+), 39 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-fortran-simplify-elemental-arguments-walking.patch --]
[-- Type: text/x-patch; name="0003-fortran-simplify-elemental-arguments-walking.patch", Size: 7147 bytes --]

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index d678c6b56dc..7e76e482b98 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2333,6 +2333,10 @@ struct gfc_dummy_arg
 #define gfc_get_dummy_arg() XCNEW (gfc_dummy_arg)
 
 
+const gfc_typespec & gfc_dummy_arg_get_typespec (gfc_dummy_arg &);
+bool gfc_dummy_arg_is_optional (gfc_dummy_arg &);
+
+
 /* Specifies the various kinds of check functions used to verify the
    argument lists of intrinsic functions. fX with X an integer refer
    to check functions of intrinsics with X arguments. f1m is used for
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index c4ec0d89a58..db0b3b01b8c 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -5503,3 +5503,37 @@ gfc_get_formal_from_actual_arglist (gfc_symbol *sym,
       f = &((*f)->next);
     }
 }
+
+
+const gfc_typespec &
+gfc_dummy_arg_get_typespec (gfc_dummy_arg & dummy_arg)
+{
+  switch (dummy_arg.intrinsicness)
+    {
+    case GFC_INTRINSIC_DUMMY_ARG:
+      return dummy_arg.u.intrinsic->ts;
+
+    case GFC_NON_INTRINSIC_DUMMY_ARG:
+      return dummy_arg.u.non_intrinsic->sym->ts;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+
+bool
+gfc_dummy_arg_is_optional (gfc_dummy_arg & dummy_arg)
+{
+  switch (dummy_arg.intrinsicness)
+    {
+    case GFC_INTRINSIC_DUMMY_ARG:
+      return dummy_arg.u.intrinsic->optional;
+
+    case GFC_NON_INTRINSIC_DUMMY_ARG:
+      return dummy_arg.u.non_intrinsic->sym->attr.optional;
+
+    default:
+      gcc_unreachable ();
+    }
+}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 79321854498..d37c1e7ad7f 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -3010,7 +3010,8 @@ gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
   /* If the expression is of polymorphic type, it's actual size is not known,
      so we avoid copying it anywhere.  */
   if (ss_info->data.scalar.dummy_arg
-      && ss_info->data.scalar.dummy_arg->ts.type == BT_CLASS
+      && gfc_dummy_arg_get_typespec (*ss_info->data.scalar.dummy_arg).type
+	 == BT_CLASS
       && ss_info->expr->ts.type == BT_CLASS)
     return true;
 
@@ -11521,9 +11522,8 @@ arg_evaluated_for_scalarization (gfc_intrinsic_sym *function,
 gfc_ss *
 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
 				  gfc_intrinsic_sym *intrinsic_sym,
-				  gfc_symbol *proc_ifc, gfc_ss_type type)
+				  gfc_ss_type type)
 {
-  gfc_formal_arglist *dummy_arg;
   int scalar;
   gfc_ss *head;
   gfc_ss *tail;
@@ -11532,15 +11532,11 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
   head = gfc_ss_terminator;
   tail = NULL;
 
-  if (proc_ifc)
-    dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
-  else
-    dummy_arg = NULL;
-
   int arg_num = 0;
   scalar = 1;
   for (; arg; arg = arg->next)
     {
+      gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
       if (!arg->expr
 	  || arg->expr->expr_type == EXPR_NULL
 	  || !arg_evaluated_for_scalarization (intrinsic_sym, *arg, arg_num))
@@ -11554,13 +11550,13 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
 	  newss = gfc_get_scalar_ss (head, arg->expr);
 	  newss->info->type = type;
 	  if (dummy_arg)
-	    newss->info->data.scalar.dummy_arg = dummy_arg->sym;
+	    newss->info->data.scalar.dummy_arg = dummy_arg;
 	}
       else
 	scalar = 0;
 
       if (dummy_arg != NULL
-	  && dummy_arg->sym->attr.optional
+	  && gfc_dummy_arg_is_optional (*dummy_arg)
 	  && arg->expr->expr_type == EXPR_VARIABLE
 	  && (gfc_expr_attr (arg->expr).optional
 	      || gfc_expr_attr (arg->expr).allocatable
@@ -11577,8 +11573,6 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
 
 loop_continue:
       arg_num++;
-      if (dummy_arg != NULL)
-	dummy_arg = dummy_arg->next;
     }
 
   if (scalar)
@@ -11638,7 +11632,6 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
       ss = gfc_walk_elemental_function_args (old_ss,
 					     expr->value.function.actual,
 					     gfc_get_intrinsic_for_expr (expr),
-					     gfc_get_proc_ifc_for_expr (expr),
 					     GFC_SS_REFERENCE);
       if (ss != old_ss
 	  && (comp
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 8f806c32f80..9c4bd06d414 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -87,7 +87,7 @@ gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref * ref);
 /* Walk the arguments of an elemental function.  */
 gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *,
 					  gfc_intrinsic_sym *,
-					  gfc_symbol *, gfc_ss_type);
+					  gfc_ss_type);
 /* Walk an intrinsic function.  */
 gfc_ss *gfc_walk_intrinsic_function (gfc_ss *, gfc_expr *,
 				     gfc_intrinsic_sym *);
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 3f867911af5..c1b51f4da26 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -11085,7 +11085,7 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
   if (isym->elemental)
     return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
 					     expr->value.function.isym,
-					     NULL, GFC_SS_SCALAR);
+					     GFC_SS_SCALAR);
 
   if (expr->rank == 0)
     return ss;
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index bdf7957c4a0..1fc6d3adda5 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -375,27 +375,6 @@ get_intrinsic_for_code (gfc_code *code)
 }
 
 
-/* Get the interface symbol for the procedure corresponding to the given call.
-   We can't get the procedure symbol directly as we have to handle the case
-   of (deferred) type-bound procedures.  */
-
-static gfc_symbol *
-get_proc_ifc_for_call (gfc_code *c)
-{
-  gfc_symbol *sym;
-
-  gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
-
-  sym = gfc_get_proc_ifc_for_expr (c->expr1);
-
-  /* Fall back/last resort try.  */
-  if (sym == NULL)
-    sym = c->resolved_sym;
-
-  return sym;
-}
-
-
 /* Translate the CALL statement.  Builds a call to an F95 subroutine.  */
 
 tree
@@ -422,7 +401,6 @@ gfc_trans_call (gfc_code * code, bool dependency_check,
   if (code->resolved_sym->attr.elemental)
     ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
 					   get_intrinsic_for_code (code),
-					   get_proc_ifc_for_call (code),
 					   GFC_SS_REFERENCE);
 
   /* MVBITS is inlined but needs the dependency checking found here.  */
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 0d4eed20d20..15012a336ff 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -266,8 +266,8 @@ typedef struct gfc_ss_info
     struct
     {
       /* If the scalar is passed as actual argument to an (elemental) procedure,
-	 this is the symbol of the corresponding dummy argument.  */
-      gfc_symbol *dummy_arg;
+	 this is the corresponding dummy argument.  */
+      gfc_dummy_arg *dummy_arg;
       tree value;
       /* Tells that the scalar is a reference to a variable that might
 	 be present on the lhs, so that we should evaluate the value

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 4/5] fortran: Delete redundant missing_arg_type field
  2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
                   ` (2 preceding siblings ...)
  2021-11-07 16:16 ` [PATCH v3 3/5] fortran: simplify elemental arguments walking Mikael Morin
@ 2021-11-07 16:16 ` Mikael Morin
  2021-11-07 16:16 ` [PATCH v3 5/5] fortran: Identify arguments by their names Mikael Morin
  2021-11-11 18:32 ` [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Thomas Koenig
  5 siblings, 0 replies; 7+ messages in thread
From: Mikael Morin @ 2021-11-07 16:16 UTC (permalink / raw)
  To: fortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 726 bytes --]


Now that we can get information about an actual arg's associated
dummy using the associated_dummy attribute, the field missing_arg_type
contains redundant information.
This removes it.

gcc/fortran/ChangeLog:
	* gfortran.h (gfc_actual_arglist::missing_arg_type): Remove.
	* interface.c (gfc_compare_actual_formal): Remove
	missing_arg_type initialization.
	* intrinsic.c (sort_actual): Ditto.
	* trans-expr.c (gfc_conv_procedure_call): Use associated_dummy
	and gfc_dummy_arg_get_typespec to get the dummy argument type.
---
 gcc/fortran/gfortran.h   | 5 -----
 gcc/fortran/interface.c  | 5 -----
 gcc/fortran/intrinsic.c  | 5 +----
 gcc/fortran/trans-expr.c | 9 +++++++--
 4 files changed, 8 insertions(+), 16 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0004-fortran-Delete-redundant-missing_arg_type-field.patch --]
[-- Type: text/x-patch; name="0004-fortran-Delete-redundant-missing_arg_type-field.patch", Size: 2648 bytes --]

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 7e76e482b98..4879805ff0b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1210,11 +1210,6 @@ typedef struct gfc_actual_arglist
   /* Alternate return label when the expr member is null.  */
   struct gfc_st_label *label;
 
-  /* This is set to the type of an eventual omitted optional
-     argument. This is used to determine if a hidden string length
-     argument has to be added to a function call.  */
-  bt missing_arg_type;
-
   gfc_param_spec_type spec_type;
 
   struct gfc_expr *expr;
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index db0b3b01b8c..36b7a852066 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -3681,11 +3681,6 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
   if (*ap == NULL && n > 0)
     *ap = new_arg[0];
 
-  /* Note the types of omitted optional arguments.  */
-  for (a = *ap, f = formal; a; a = a->next, f = f->next)
-    if (a->expr == NULL && a->label == NULL)
-      a->missing_arg_type = f->sym->ts.type;
-
   return true;
 }
 
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index f6d061a847c..3018315ed78 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -4405,10 +4405,7 @@ do_sort:
 	}
 
       if (a == NULL)
-	{
-	  a = gfc_get_actual_arglist ();
-	  a->missing_arg_type = f->ts.type;
-	}
+	a = gfc_get_actual_arglist ();
 
       a->associated_dummy = get_intrinsic_dummy_arg (f);
 
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index e7aec3845d3..bc502c0f43c 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6157,7 +6157,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 		{
 		  /* Pass a NULL pointer for an absent arg.  */
 		  parmse.expr = null_pointer_node;
-		  if (arg->missing_arg_type == BT_CHARACTER)
+		  gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
+		  if (dummy_arg
+		      && gfc_dummy_arg_get_typespec (*dummy_arg).type
+			 == BT_CHARACTER)
 		    parmse.string_length = build_int_cst (gfc_charlen_type_node,
 							  0);
 		}
@@ -6174,7 +6177,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 			  || !CLASS_DATA (fsym)->attr.allocatable));
 	  gfc_init_se (&parmse, NULL);
 	  parmse.expr = null_pointer_node;
-	  if (arg->missing_arg_type == BT_CHARACTER)
+	  if (arg->associated_dummy
+	      && gfc_dummy_arg_get_typespec (*arg->associated_dummy).type
+		 == BT_CHARACTER)
 	    parmse.string_length = build_int_cst (gfc_charlen_type_node, 0);
 	}
       else if (fsym && fsym->ts.type == BT_CLASS

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 5/5] fortran: Identify arguments by their names
  2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
                   ` (3 preceding siblings ...)
  2021-11-07 16:16 ` [PATCH v3 4/5] fortran: Delete redundant missing_arg_type field Mikael Morin
@ 2021-11-07 16:16 ` Mikael Morin
  2021-11-11 18:32 ` [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Thomas Koenig
  5 siblings, 0 replies; 7+ messages in thread
From: Mikael Morin @ 2021-11-07 16:16 UTC (permalink / raw)
  To: fortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 884 bytes --]


This provides a new function to get the name of a dummy argument,
so that identifying an argument can be made using just its name
instead of a mix of name matching (for keyword actual arguments)
and argument counting (for other actual arguments).

gcc/fortran/ChangeLog:
	* interface.c (gfc_dummy_arg_get_name): New function.
	* gfortran.h (gfc_dummy_arg_get_name): Declare it.
	* trans-array.c (arg_evaluated_for_scalarization): Pass a dummy
	argument wrapper as argument instead of an actual argument
	and an index number.  Check it’s non-NULL.  Use its name
	to identify it.
	(gfc_walk_elemental_function_args): Update call to
	arg_evaluated for scalarization.  Remove argument counting.
---
 gcc/fortran/gfortran.h    |  1 +
 gcc/fortran/interface.c   | 17 +++++++++++++++++
 gcc/fortran/trans-array.c | 16 +++++-----------
 3 files changed, 23 insertions(+), 11 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0005-fortran-Identify-arguments-by-their-names.patch --]
[-- Type: text/x-patch; name="0005-fortran-Identify-arguments-by-their-names.patch", Size: 2735 bytes --]

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 4879805ff0b..ac4b3a8b6d4 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2328,6 +2328,7 @@ struct gfc_dummy_arg
 #define gfc_get_dummy_arg() XCNEW (gfc_dummy_arg)
 
 
+const char * gfc_dummy_arg_get_name (gfc_dummy_arg &);
 const gfc_typespec & gfc_dummy_arg_get_typespec (gfc_dummy_arg &);
 bool gfc_dummy_arg_is_optional (gfc_dummy_arg &);
 
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 36b7a852066..d87088f988d 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -5500,6 +5500,23 @@ gfc_get_formal_from_actual_arglist (gfc_symbol *sym,
 }
 
 
+const char *
+gfc_dummy_arg_get_name (gfc_dummy_arg & dummy_arg)
+{
+  switch (dummy_arg.intrinsicness)
+    {
+    case GFC_INTRINSIC_DUMMY_ARG:
+      return dummy_arg.u.intrinsic->name;
+
+    case GFC_NON_INTRINSIC_DUMMY_ARG:
+      return dummy_arg.u.non_intrinsic->sym->name;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+
 const gfc_typespec &
 gfc_dummy_arg_get_typespec (gfc_dummy_arg & dummy_arg)
 {
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index d37c1e7ad7f..2090adf01e7 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -11492,16 +11492,14 @@ gfc_get_intrinsic_for_expr (gfc_expr *call)
 
 static bool
 arg_evaluated_for_scalarization (gfc_intrinsic_sym *function,
-				 gfc_actual_arglist &actual_arg, int arg_num)
+				 gfc_dummy_arg *dummy_arg)
 {
-  if (function != NULL)
+  if (function != NULL && dummy_arg != NULL)
     {
       switch (function->id)
 	{
 	  case GFC_ISYM_INDEX:
-	    if ((actual_arg.name == NULL && arg_num == 3)
-		|| (actual_arg.name != NULL
-		    && strcmp ("kind", actual_arg.name) == 0))
+	    if (strcmp ("kind", gfc_dummy_arg_get_name (*dummy_arg)) == 0)
 	      return false;
 	  /* Fallthrough.  */
 
@@ -11532,15 +11530,14 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
   head = gfc_ss_terminator;
   tail = NULL;
 
-  int arg_num = 0;
   scalar = 1;
   for (; arg; arg = arg->next)
     {
       gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
       if (!arg->expr
 	  || arg->expr->expr_type == EXPR_NULL
-	  || !arg_evaluated_for_scalarization (intrinsic_sym, *arg, arg_num))
-	goto loop_continue;
+	  || !arg_evaluated_for_scalarization (intrinsic_sym, dummy_arg))
+	continue;
 
       newss = gfc_walk_subexpr (head, arg->expr);
       if (newss == head)
@@ -11570,9 +11567,6 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
           while (tail->next != gfc_ss_terminator)
             tail = tail->next;
         }
-
-loop_continue:
-      arg_num++;
     }
 
   if (scalar)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896]
  2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
                   ` (4 preceding siblings ...)
  2021-11-07 16:16 ` [PATCH v3 5/5] fortran: Identify arguments by their names Mikael Morin
@ 2021-11-11 18:32 ` Thomas Koenig
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Koenig @ 2021-11-11 18:32 UTC (permalink / raw)
  To: Mikael Morin, fortran, gcc-patches


Hi Mikael,

> Regression-tested on x86_64-linux-gnu.  Ok for master?

This looks quite good, and is (I think) a cleaner version than
what we had before.  OK.

Thanks a lot for the patch(es)!

Best regards

	Thomas

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-11-11 18:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-07 16:16 [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Mikael Morin
2021-11-07 16:16 ` [PATCH v3 1/5] fortran: Tiny sort_actual internal refactoring Mikael Morin
2021-11-07 16:16 ` [PATCH v3 2/5] fortran: Reverse actual vs dummy argument mapping Mikael Morin
2021-11-07 16:16 ` [PATCH v3 3/5] fortran: simplify elemental arguments walking Mikael Morin
2021-11-07 16:16 ` [PATCH v3 4/5] fortran: Delete redundant missing_arg_type field Mikael Morin
2021-11-07 16:16 ` [PATCH v3 5/5] fortran: Identify arguments by their names Mikael Morin
2021-11-11 18:32 ` [PATCH v3 0/5] fortran: Ignore unused arguments for scalarisation [PR97896] Thomas Koenig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).