diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2011-04-04 20:55:02 +0000 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2011-04-04 20:55:02 +0000 |
commit | 9046a4dcc9e0c7c94f5f917740097d954d2c868d (patch) | |
tree | 82f9b1e3bdf10c2b9aeeb4ffe439dd074f6a47c5 /gcc/fortran/frontend-passes.c | |
parent | 128e09f93d6fa5fc367ad2be059c6dd674ef1049 (diff) | |
download | gcc-9046a4dcc9e0c7c94f5f917740097d954d2c868d.zip gcc-9046a4dcc9e0c7c94f5f917740097d954d2c868d.tar.gz gcc-9046a4dcc9e0c7c94f5f917740097d954d2c868d.tar.bz2 |
frontend-passes: (optimize_lexical_comparison): New function.
2010-04-04 Thomas Koenig <tkoenig@gcc.gnu.org>
* frontend-passes: (optimize_lexical_comparison): New function.
(optimize_expr): Call it.
(optimize_comparison): Also handle lexical comparison functions.
Return false instad of -2 for unequal comparison.
2010-04-04 Thomas Koenig <tkoenig@gcc.gnu.org>
* gfortran.dg/character_comparison_8.f90: New test.
From-SVN: r171953
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r-- | gcc/fortran/frontend-passes.c | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index c2f6bd5..b6f6b4c 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -35,6 +35,7 @@ static void optimize_assignment (gfc_code *); static bool optimize_op (gfc_expr *); static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op); static bool optimize_trim (gfc_expr *); +static bool optimize_lexical_comparison (gfc_expr *); /* How deep we are inside an argument list. */ @@ -119,6 +120,9 @@ optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, if (optimize_trim (*e)) gfc_simplify_expr (*e, 0); + if (optimize_lexical_comparison (*e)) + gfc_simplify_expr (*e, 0); + if ((*e)->expr_type == EXPR_OP && optimize_op (*e)) gfc_simplify_expr (*e, 0); @@ -483,6 +487,34 @@ strip_function_call (gfc_expr *e) } +/* Optimization of lexical comparison functions. */ + +static bool +optimize_lexical_comparison (gfc_expr *e) +{ + if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL) + return false; + + switch (e->value.function.isym->id) + { + case GFC_ISYM_LLE: + return optimize_comparison (e, INTRINSIC_LE); + + case GFC_ISYM_LGE: + return optimize_comparison (e, INTRINSIC_GE); + + case GFC_ISYM_LGT: + return optimize_comparison (e, INTRINSIC_GT); + + case GFC_ISYM_LLT: + return optimize_comparison (e, INTRINSIC_LT); + + default: + break; + } + return false; +} + /* Recursive optimization of operators. */ static bool @@ -522,9 +554,25 @@ optimize_comparison (gfc_expr *e, gfc_intrinsic_op op) bool change; int eq; bool result; + gfc_actual_arglist *firstarg, *secondarg; - op1 = e->value.op.op1; - op2 = e->value.op.op2; + if (e->expr_type == EXPR_OP) + { + firstarg = NULL; + secondarg = NULL; + op1 = e->value.op.op1; + op2 = e->value.op.op2; + } + else if (e->expr_type == EXPR_FUNCTION) + { + /* One of the lexical comparision functions. */ + firstarg = e->value.function.actual; + secondarg = firstarg->next; + op1 = firstarg->expr; + op2 = secondarg->expr; + } + else + gcc_unreachable (); /* Strip off unneeded TRIM calls from string comparisons. */ @@ -587,13 +635,21 @@ optimize_comparison (gfc_expr *e, gfc_intrinsic_op op) && op2_left->expr_type == EXPR_CONSTANT && op1_left->value.character.length != op2_left->value.character.length) - return -2; + return false; else { gfc_free (op1_left); gfc_free (op2_left); - e->value.op.op1 = op1_right; - e->value.op.op2 = op2_right; + if (firstarg) + { + firstarg->expr = op1_right; + secondarg->expr = op2_right; + } + else + { + e->value.op.op1 = op1_right; + e->value.op.op2 = op2_right; + } optimize_comparison (e, op); return true; } @@ -602,8 +658,17 @@ optimize_comparison (gfc_expr *e, gfc_intrinsic_op op) { gfc_free (op1_right); gfc_free (op2_right); - e->value.op.op1 = op1_left; - e->value.op.op2 = op2_left; + if (firstarg) + { + firstarg->expr = op1_left; + secondarg->expr = op2_left; + } + else + { + e->value.op.op1 = op1_left; + e->value.op.op2 = op2_left; + } + optimize_comparison (e, op); return true; } |