aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/frontend-passes.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2010-09-06 21:40:15 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2010-09-06 21:40:15 +0000
commit5c599206d359e16c9f9e132c06e6bed53b360e29 (patch)
tree7f483f37e3085a9a70ddb013265554c37adaa91e /gcc/fortran/frontend-passes.c
parent4e18507b6834ce629c8bef80adacb19ef205279f (diff)
downloadgcc-5c599206d359e16c9f9e132c06e6bed53b360e29.zip
gcc-5c599206d359e16c9f9e132c06e6bed53b360e29.tar.gz
gcc-5c599206d359e16c9f9e132c06e6bed53b360e29.tar.bz2
re PR fortran/36931 (unneeded temporary for array intrinsic binop scalar)
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/36931 * gfortran.dg/dependency_35.f90: New test. From-SVN: r163934
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r--gcc/fortran/frontend-passes.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 14c5fe4..17b31fe 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -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. */