Patchwork [fortran] Fix PR 36931, more array dependencies

login
register
mail settings
Submitter Thomas Koenig
Date Sept. 3, 2010, 10:58 p.m.
Message ID <1283554721.4759.23.camel@linux-fd1f.site>
Download mbox | patch
Permalink /patch/63732/
State New
Headers show

Comments

Thomas Koenig - Sept. 3, 2010, 10:58 p.m.
Hello world,

here a few more temporary eliminations, for code like

  a = f() + b

After unsuccessfully trying to understand how to do this in trans-*,
I used a transformation of the front end trees, in the front end
optimization pass.

Regression-tested.  OK for trunk?

	Thomas

2010-09-04  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/36931
	* frontend-passes.c (optimize_binop_array_assignment):  New
	function.
	(optimize_assignment):  Call it.

2010-09-04  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/36931
	* gfortran.dg/dependency_35.f90:  New test.
Steven Bosscher - Sept. 4, 2010, 7:52 p.m.
On Sat, Sep 4, 2010 at 12:58 AM, Thomas Koenig <tkoenig@netcologne.de> wrote:
> Hello world,
>
> here a few more temporary eliminations, for code like
>
>  a = f() + b


So what happens with "a = f() + g() + h" e.g. a = matmul(b,c) +
matmul(d,e) + f" ?

Ciao!
Steven
Thomas Koenig - Sept. 4, 2010, 9:02 p.m.
Hi Steven,

> On Sat, Sep 4, 2010 at 12:58 AM, Thomas Koenig <tkoenig@netcologne.de> wrote:
> > Hello world,
> >
> > here a few more temporary eliminations, for code like
> >
> >  a = f() + b
> 
> 
> So what happens with "a = f() + g() + h" e.g. a = matmul(b,c) +
> matmul(d,e) + f" ?
> 

In the first step, this is converted to

a = matmul(b,c)
a = a + matmul(d,e) + f

When optimize_assignment looks at the second statement again,
gfc_check_dependency finds the dependency between the lhs and
rhs, and the optimization is not run again.

When you look at the patch, the difference is easy to spot in the
*.original file with and without -O (because this part is run only
with optimization).

	Thomas
Thomas Koenig - Sept. 6, 2010, 7:16 p.m.
Am Samstag, den 04.09.2010, 00:58 +0200 schrieb Thomas Koenig:
> Hello world,
> 
> here a few more temporary eliminations, for code like
> 
>   a = f() + b

Ping **0.125 ?

	Thomas
Mikael Morin - Sept. 6, 2010, 8:09 p.m.
Le 06.09.2010 21:16, Thomas Koenig a écrit :
>
> Am Samstag, den 04.09.2010, 00:58 +0200 schrieb Thomas Koenig:
>> Hello world,
>>
>> here a few more temporary eliminations, for code like
>>
>>    a = f() + b
>
> Ping **0.125 ?
>
> 	Thomas
>
>

OK.
Thomas Koenig - Sept. 6, 2010, 9:41 p.m.
Hello Mikael,

> Le 06.09.2010 21:16, Thomas Koenig a écrit :
> >
> > Am Samstag, den 04.09.2010, 00:58 +0200 schrieb Thomas Koenig:
> >> Hello world,
> >>
> >> here a few more temporary eliminations, for code like
> >>
> >>    a = f() + b
> >
> > Ping **0.125 ?
> >
> > 	Thomas
> >
> >
> 
> OK.
> 

Sende          fortran/ChangeLog
Sende          fortran/frontend-passes.c
Sende          testsuite/ChangeLog
Hinzufügen     testsuite/gfortran.dg/dependency_35.f90
Übertrage Daten ....
Revision 163934 übertragen.

Thanks a lot for the review!

I'll try to do more on your transpose patch tomorrow.

	Thomas

Patch

Index: frontend-passes.c
===================================================================
--- frontend-passes.c	(Revision 163846)
+++ frontend-passes.c	(Arbeitskopie)
@@ -235,6 +235,77 @@  optimize_code_node (gfc_code *c)
     }
 }
 
+/* Replace code like
+   a = matmul(b,c) + d
+   with
+   a = matmul(b,c) ;   a = a + d
+   where the array function is not elemental and not allocatable
+   and does not depend on the left-hand side.
+*/
+
+static bool
+optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
+{
+  gfc_expr *e;
+
+  e = *rhs;
+  if (e->expr_type == EXPR_OP)
+    {
+      switch (e->value.op.op)
+	{
+	  /* Unary operators and exponentiation: Only look at a single
+	     operand.  */
+	case INTRINSIC_NOT:
+	case INTRINSIC_UPLUS:
+	case INTRINSIC_UMINUS:
+	case INTRINSIC_PARENTHESES:
+	case INTRINSIC_POWER:
+	  if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
+	    return true;
+	  break;
+
+	default:
+	  /* Binary operators.  */
+	  if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
+	    return true;
+
+	  if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
+	    return true;
+
+	  break;
+	}
+    }
+  else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
+	   && ! (e->value.function.esym 
+		 && (e->value.function.esym->attr.elemental 
+		     || e->value.function.esym->attr.allocatable))
+	   && ! (e->value.function.isym && e->value.function.isym->elemental))
+    {
+
+      gfc_code *n;
+      gfc_expr *new_expr;
+
+      /* Insert a new assignment statement after the current one.  */
+      n = XCNEW (gfc_code);
+      n->op = EXEC_ASSIGN;
+      n->loc = c->loc;
+      n->next = c->next;
+      c->next = n;
+
+      n->expr1 = gfc_copy_expr (c->expr1);
+      n->expr2 = c->expr2;
+      new_expr = gfc_copy_expr (c->expr1);
+      c->expr2 = e;
+      *rhs = new_expr;
+      
+      return true;
+
+    }
+
+  /* Nothing to optimize.  */
+  return false;
+}
+
 /* Optimizations for an assignment.  */
 
 static void
@@ -259,6 +330,13 @@  optimize_assignment (gfc_code * c)
 	}
     }
 
+  if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
+    optimize_binop_array_assignment (c, &rhs, false);
+
+  /* If we insert a statement after the current one, the surrounding loop in
+     optimize_code will call optimize_assignment on the inserted statement
+     anyway, so there is no need to call optimize_assignment again.  */
+
   /* All direct optimizations have been done.  Now it's time
      to optimize the rhs.  */