diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2013-03-28 21:02:00 +0000 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2013-03-28 21:02:00 +0000 |
commit | 4099436d98dcdd96a0cbfd4332da1ddc961ba7f7 (patch) | |
tree | 1bf1d4747ca9b4c3527169167457134da4610898 /gcc/fortran/frontend-passes.c | |
parent | 777e69760d2e68900b2b9460124c2327e651cca2 (diff) | |
download | gcc-4099436d98dcdd96a0cbfd4332da1ddc961ba7f7.zip gcc-4099436d98dcdd96a0cbfd4332da1ddc961ba7f7.tar.gz gcc-4099436d98dcdd96a0cbfd4332da1ddc961ba7f7.tar.bz2 |
re PR fortran/55806 (Missed optimization with ANY or ALL)
2013-03-28 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/55806
* frontend-passes.c (optimize_code): Keep track of
current code to make code insertion possible.
(combine_array_constructor): New function.
(optimize_op): Call it.
2013-03-28 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/55806
* gfortran.dg/array_constructor_43.f90: New test.
* gfortran.dg/random_seed_3.f90: New test.
From-SVN: r197216
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r-- | gcc/fortran/frontend-passes.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index ead32f8..a77afc5 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -135,6 +135,10 @@ optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, else count_arglist = 0; + current_code = c; + inserted_block = NULL; + changed_statement = NULL; + if (op == EXEC_ASSIGN) optimize_assignment (*c); return 0; @@ -991,13 +995,98 @@ optimize_lexical_comparison (gfc_expr *e) return false; } +/* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not + do CHARACTER because of possible pessimization involving character + lengths. */ + +static bool +combine_array_constructor (gfc_expr *e) +{ + + gfc_expr *op1, *op2; + gfc_expr *scalar; + gfc_expr *new_expr; + gfc_constructor *c, *new_c; + gfc_constructor_base oldbase, newbase; + bool scalar_first; + + /* Array constructors have rank one. */ + if (e->rank != 1) + return false; + + op1 = e->value.op.op1; + op2 = e->value.op.op2; + + if (op1->expr_type == EXPR_ARRAY && op2->rank == 0) + scalar_first = false; + else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0) + { + scalar_first = true; + op1 = e->value.op.op2; + op2 = e->value.op.op1; + } + else + return false; + + if (op2->ts.type == BT_CHARACTER) + return false; + + if (op2->expr_type == EXPR_CONSTANT) + scalar = gfc_copy_expr (op2); + else + scalar = create_var (gfc_copy_expr (op2)); + + oldbase = op1->value.constructor; + newbase = NULL; + e->expr_type = EXPR_ARRAY; + + c = gfc_constructor_first (oldbase); + + for (c = gfc_constructor_first (oldbase); c; + c = gfc_constructor_next (c)) + { + new_expr = gfc_get_expr (); + new_expr->ts = e->ts; + new_expr->expr_type = EXPR_OP; + new_expr->rank = c->expr->rank; + new_expr->where = c->where; + new_expr->value.op.op = e->value.op.op; + + if (scalar_first) + { + new_expr->value.op.op1 = gfc_copy_expr (scalar); + new_expr->value.op.op2 = gfc_copy_expr (c->expr); + } + else + { + new_expr->value.op.op1 = gfc_copy_expr (c->expr); + new_expr->value.op.op2 = gfc_copy_expr (scalar); + } + + new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where)); + new_c->iterator = c->iterator; + c->iterator = NULL; + } + + gfc_free_expr (op1); + gfc_free_expr (op2); + + e->value.constructor = newbase; + return true; +} + + /* Recursive optimization of operators. */ static bool optimize_op (gfc_expr *e) { + bool changed; + gfc_intrinsic_op op = e->value.op.op; + changed = false; + /* Only use new-style comparisons. */ switch(op) { @@ -1037,7 +1126,15 @@ optimize_op (gfc_expr *e) case INTRINSIC_NE: case INTRINSIC_GT: case INTRINSIC_LT: - return optimize_comparison (e, op); + changed = optimize_comparison (e, op); + + /* Fall through */ + /* Look at array constructors. */ + case INTRINSIC_PLUS: + case INTRINSIC_MINUS: + case INTRINSIC_TIMES: + case INTRINSIC_DIVIDE: + return combine_array_constructor (e) || changed; default: break; |