public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Mikael Morin <mikael.morin@sfr.fr>
To: Thomas Koenig <tkoenig@netcologne.de>
Cc: "fortran@gcc.gnu.org" <fortran@gcc.gnu.org>,
	gcc-patches	<gcc-patches@gcc.gnu.org>
Subject: Re: [patch, Fortran] PR 55806 - Inefficient ANY with array constructors
Date: Fri, 11 Jan 2013 19:53:00 -0000	[thread overview]
Message-ID: <50F06DB9.40102@sfr.fr> (raw)
In-Reply-To: <50E344A6.1000802@netcologne.de>

Le 01/01/2013 21:18, Thomas Koenig a écrit :
> Hello world,
>
> the attached patch replaces ANY(a, b, c) with a .or. b .or c,
> leading to reduced execution time. It also handles ALL, PRODUCT
> and SUM.
>
> This fixes a bug noted by Michael Metcalf.
>
> Regression-tested. OK for trunk?
>
A few comments below.

Mikael

> Index: frontend-passes.c
> ===================================================================
> --- frontend-passes.c	(Revision 194760)
> +++ frontend-passes.c	(Arbeitskopie)
> @@ -180,7 +183,172 @@ optimize_expr (gfc_expr **e, int *walk_subtrees AT
>    return 0;
>  }
>
> +/* Auxiliary function to handle the arguments to reduction intrnisics.
> +   If the function is a scalar, just copy it; otherwise Returns the new
> +   element, the old one can be freed.  */
>
> +static gfc_expr *
> +copy_walk_reduction_arg (gfc_expr *e, gfc_expr *fn)
> +{
> +  gfc_expr *fcn;
> +  const char *new_name;
> +  gfc_actual_arglist *actual_arglist;
> +
> +  if (e->rank == 0 || e->expr_type == EXPR_FUNCTION)
> +    fcn = gfc_copy_expr (e);
> +  else
> +    {
> +      fcn = gfc_get_expr ();
> +      fcn->expr_type = EXPR_FUNCTION;
> +      fcn->value.function.isym = fn->value.function.isym;
> +      actual_arglist = gfc_get_actual_arglist ();
> +      actual_arglist->expr = gfc_copy_expr (e);
> +      actual_arglist->next = gfc_get_actual_arglist ();
Another one is needed.  I get a segmentation fault with SUM.

[...]
> +
> +/* Callback function for optimzation of reductions to scalars.  Transform
> +   ANY ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY,
> +   SUM and PRODUCT correspondingly.  Handly only the simple cases without
> +   MASK and DIM.  */
> +
> +static int
> +callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
> +		    void *data ATTRIBUTE_UNUSED)
> +{
> +  gfc_expr *fn, *arg;
> +  gfc_intrinsic_op op;
> +  gfc_isym_id id;
> +  gfc_actual_arglist *a;
> +  gfc_actual_arglist *dim;
> +  gfc_constructor *c;
> +  gfc_expr *res, *new_expr;
> +
> +  fn = *e;
> +
> +  if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
> +      || fn->value.function.isym == NULL)
> +    return 0;
> +
> +  id = fn->value.function.isym->id;
> +
> +  if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
> +      && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
> +    return 0;
> +
> +  a = fn->value.function.actual;
> +
> +  /* Don't handle MASK or DIM.  */
> +
> +  dim = a->next;
> +
> +  if (dim != NULL)
> +    {
Minor, but I think you can assume dim != NULL.  Same for mask.

> +      gfc_actual_arglist *mask;
> +
> +      if (dim->expr != NULL)
> +	return 0;
> +
> +      mask = dim->next;
> +      if (mask != NULL)
> +	if ( mask->expr != NULL)
> +	  return 0;
> +    }
> +
> +  arg = a->expr;
> +
> +  if (arg->expr_type != EXPR_ARRAY)
> +    return 0;
> +
> +  switch (id)
> +    {
> +    case GFC_ISYM_SUM:
> +      op = INTRINSIC_PLUS;
> +      break;
> +
> +    case GFC_ISYM_PRODUCT:
> +      op = INTRINSIC_TIMES;
> +      break;
> +
> +    case GFC_ISYM_ANY:
> +      op = INTRINSIC_OR;
> +      break;
> +
> +    case GFC_ISYM_ALL:
> +      op = INTRINSIC_AND;
> +      break;
> +
> +    default:
> +      return 0;
> +    }
> +
> +  c = gfc_constructor_first (arg->value.constructor);
> +
> +  if (c == NULL)
> +    return 0;
> +
> +  res = copy_walk_reduction_arg (c->expr, fn);
> +
> +  c = gfc_constructor_next (c);
> +  while (c)
> +    {
> +      new_expr = gfc_get_expr ();
> +      new_expr->ts = fn->ts;
> +      new_expr->expr_type = EXPR_OP;
> +      new_expr->rank = fn->rank;
> +      new_expr->where = fn->where;
> +      new_expr->value.op.op = op;
> +      new_expr->value.op.op1 = res;
> +      new_expr->value.op.op2 = copy_walk_reduction_arg (c->expr, fn);
> +      res = new_expr;
> +      c = gfc_constructor_next (c);
> +    }
> +
> +  gfc_simplify_expr (res, 0);
> +  *e = res;
> +  gfc_free_expr (fn);
> +
> +  /* We changed things from under the expression walker.  Walking the
> +     old tree would mess up things, so let's not do that.  */
> +  return 1;
I think this prevents any further reduction optimization. The following 
variant of your test case doesn't avoid the temporary:

     do i=1,3
        if (any([abs(a(i,1) - b(i,1)) > acc,  &
             (j==i+1,j=3,8)])) cycle
        if (any([abs(a(i,2) - b(i,2)) > acc, &
             abs(a(i,3) - b(i,3)) > acc, lo(i,:)])) cycle
        c = c + i
     end do

  parent reply	other threads:[~2013-01-11 19:53 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-01 20:18 Thomas Koenig
2013-01-06 16:33 ` Thomas Koenig
2013-01-08 23:16   ` *ping* " Thomas Koenig
2013-01-11 19:53 ` Mikael Morin [this message]
2013-01-13 22:14   ` Thomas Koenig
2013-01-14 13:29     ` Mikael Morin
2013-01-14 21:51       ` Thomas Koenig
2017-11-02 10:27         ` Bernhard Reutner-Fischer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=50F06DB9.40102@sfr.fr \
    --to=mikael.morin@sfr.fr \
    --cc=fortran@gcc.gnu.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=tkoenig@netcologne.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).