diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2010-09-06 21:40:15 +0000 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2010-09-06 21:40:15 +0000 |
commit | 5c599206d359e16c9f9e132c06e6bed53b360e29 (patch) | |
tree | 7f483f37e3085a9a70ddb013265554c37adaa91e /gcc/fortran/frontend-passes.c | |
parent | 4e18507b6834ce629c8bef80adacb19ef205279f (diff) | |
download | gcc-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.c | 78 |
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. */ |