OSDN Git Service

2010-09-06 Thomas Koenig <tkoenig@gcc.gnu.org>
authortkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 6 Sep 2010 21:40:15 +0000 (21:40 +0000)
committertkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 6 Sep 2010 21:40:15 +0000 (21:40 +0000)
PR fortran/36931
* frontend-passes.c (optimize_binop_array_assignment):  New
function.
(optimize_assignment):  Call it.

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

PR fortran/36931
* gfortran.dg/dependency_35.f90:  New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163934 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/fortran/ChangeLog
gcc/fortran/frontend-passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/dependency_35.f90 [new file with mode: 0644]

index d35cedc..22810de 100644 (file)
@@ -1,5 +1,12 @@
 2010-09-06  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
+       PR fortran/36931
+       * frontend-passes.c (optimize_binop_array_assignment):  New
+       function.
+       (optimize_assignment):  Call it.
+
+2010-09-06  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
        PR fortran/34145
        * trans-expr.c (gfc_conv_substring):  If start and end
        of the string reference are equal, set the length to one.
index 14c5fe4..17b31fe 100644 (file)
@@ -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.  */
 
index 362f5d1..cf07101 100644 (file)
@@ -1,5 +1,10 @@
 2010-09-06  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
+       PR fortran/36931
+       * gfortran.dg/dependency_35.f90:  New test.
+
+2010-09-06  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
        PR fortran/34145
        * gfortran.dg/char_length_17.f90:  New test.
 
diff --git a/gcc/testsuite/gfortran.dg/dependency_35.f90 b/gcc/testsuite/gfortran.dg/dependency_35.f90
new file mode 100644 (file)
index 0000000..11b9e8b
--- /dev/null
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-options "-Warray-temporaries -O" }
+module foo
+  implicit none
+contains
+  pure function bar(i,j)
+    integer, intent(in) :: i,j
+    integer, dimension(2,2) :: bar
+    bar = 33
+  end function bar
+end module foo
+
+program main
+  use foo
+  implicit none
+  integer a(2,2), b(2,2),c(2,2), d(2,2), e(2)
+
+  read (*,*) b, c, d
+  a = matmul(b,c) + d
+  a = b + bar(3,4)
+  a = bar(3,4)*5 + b
+  e = sum(b,1) + 3
+end program main
+! { dg-final { cleanup-modules "foo" } }