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.
}
}
+/* 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
}
}
+ 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. */
--- /dev/null
+! { 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" } }