diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2011-03-27 17:40:26 +0000 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2011-03-27 17:40:26 +0000 |
commit | 7e3b6543e0a188283f2307019e835eeb77cdf795 (patch) | |
tree | 5f8e7e59135cea0ccb12d23b4052ba0a4b3989dd /gcc/fortran/frontend-passes.c | |
parent | 15ea09a082e6964a4abbc49a6834cf5ab705813a (diff) | |
download | gcc-7e3b6543e0a188283f2307019e835eeb77cdf795.zip gcc-7e3b6543e0a188283f2307019e835eeb77cdf795.tar.gz gcc-7e3b6543e0a188283f2307019e835eeb77cdf795.tar.bz2 |
re PR fortran/47065 (Replace trim(a) by a(1:len_trim(a)))
2011-03-27 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/47065
* frontend-passes (optimize_trim): Also follow references, except
when they are substring references or array references.
2011-03-27 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/47065
* gfortran.dg/trim_optimize_5.f90: New test.
* gfortran.dg/trim_optimize_6.f90: New test.
From-SVN: r171575
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r-- | gcc/fortran/frontend-passes.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index e26ae68..2051b0c 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -664,6 +664,7 @@ optimize_trim (gfc_expr *e) gfc_ref *ref; gfc_expr *fcn; gfc_actual_arglist *actual_arglist, *next; + gfc_ref **rr = NULL; /* Don't do this optimization within an argument list, because otherwise aliasing issues may occur. */ @@ -681,46 +682,54 @@ optimize_trim (gfc_expr *e) if (a->expr_type != EXPR_VARIABLE) return false; + /* Follow all references to find the correct place to put the newly + created reference. FIXME: Also handle substring references and + array references. Array references cause strange regressions at + the moment. */ + if (a->ref) { - /* FIXME - also handle substring references, by modifying the - reference itself. Make sure not to evaluate functions in - the references twice. */ - return false; + for (rr = &(a->ref); *rr; rr = &((*rr)->next)) + { + if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY) + return false; + } } - else - { - strip_function_call (e); - /* Create the reference. */ + strip_function_call (e); - ref = gfc_get_ref (); - ref->type = REF_SUBSTRING; + if (e->ref == NULL) + rr = &(e->ref); - /* Set the start of the reference. */ + /* Create the reference. */ - ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); + ref = gfc_get_ref (); + ref->type = REF_SUBSTRING; - /* Build the function call to len_trim(x, gfc_defaul_integer_kind). */ + /* Set the start of the reference. */ - fcn = gfc_get_expr (); - fcn->expr_type = EXPR_FUNCTION; - fcn->value.function.isym = - gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM); - actual_arglist = gfc_get_actual_arglist (); - actual_arglist->expr = gfc_copy_expr (e); - next = gfc_get_actual_arglist (); - next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, - gfc_default_integer_kind); - actual_arglist->next = next; - fcn->value.function.actual = actual_arglist; + ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); - /* Set the end of the reference to the call to len_trim. */ + /* Build the function call to len_trim(x, gfc_defaul_integer_kind). */ - ref->u.ss.end = fcn; - e->ref = ref; - return true; - } + fcn = gfc_get_expr (); + fcn->expr_type = EXPR_FUNCTION; + fcn->value.function.isym = + gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM); + actual_arglist = gfc_get_actual_arglist (); + actual_arglist->expr = gfc_copy_expr (e); + next = gfc_get_actual_arglist (); + next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, + gfc_default_integer_kind); + actual_arglist->next = next; + fcn->value.function.actual = actual_arglist; + + /* Set the end of the reference to the call to len_trim. */ + + ref->u.ss.end = fcn; + gcc_assert (*rr == NULL); + *rr = ref; + return true; } #define WALK_SUBEXPR(NODE) \ |