This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch, fortran] PR 40628, optimize TRIM on assignment
- From: Thomas Koenig <tkoenig at netcologne dot de>
- To: fortran at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 18 Jun 2010 23:45:15 +0200
- Subject: [patch, fortran] PR 40628, optimize TRIM on assignment
Hello world,
this patch fixes one part of PR 40628 by optimizing away an unneeded
TRIM on string assignment.
I have created a new file for this, optimize.c. This is supposed to
contain optimizations with gfc_expr, before translations into TREEs.
Chances are this file will grow a bit later :-) right now it only
contains this single optimization.
At a later stage, it might be a good idea to add a -fdump-optimized-tree
to see what the optimization has done.
Regression-tested on x86_64-unknown-linux-gnu.
OK in principle for the idea? OK for trunk?
Thomas
2010-06-18 Thomas Koenig <tkoenig@gcc.gnu.org>
* Make-lang.in: Add fortran/optimize.o.
* gfortran.h: Add prototype for gfc_optimize_namespace.
* trans-decl.c (gfc_generate_function_code): If optimizing,
call gfc_optimize_namespace.
* optimize.c: New file.
Index: Make-lang.in
===================================================================
--- Make-lang.in (Revision 160943)
+++ Make-lang.in (Arbeitskopie)
@@ -66,7 +66,7 @@ F95_OBJS = $(F95_PARSER_OBJS) $(FORTRAN_TARGET_OBJ
fortran/trans.o fortran/trans-array.o fortran/trans-common.o \
fortran/trans-const.o fortran/trans-decl.o fortran/trans-expr.o \
fortran/trans-intrinsic.o fortran/trans-io.o fortran/trans-openmp.o \
- fortran/trans-stmt.o fortran/trans-types.o
+ fortran/trans-stmt.o fortran/trans-types.o fortran/optimize.o
fortran_OBJS = $(F95_OBJS) gfortranspec.o
Index: gfortran.h
===================================================================
--- gfortran.h (Revision 160943)
+++ gfortran.h (Arbeitskopie)
@@ -2825,4 +2825,8 @@ gfc_symtree* gfc_get_tbp_symtree (gfc_symtree**, c
#define CLASS_DATA(sym) sym->ts.u.derived->components
+/* optimize.c */
+
+void gfc_optimize_namespace (gfc_namespace *);
+
#endif /* GCC_GFORTRAN_H */
Index: trans-decl.c
===================================================================
--- trans-decl.c (Revision 160943)
+++ trans-decl.c (Arbeitskopie)
@@ -4371,6 +4371,9 @@ gfc_generate_function_code (gfc_namespace * ns)
int rank;
bool is_recursive;
+ if (optimize)
+ gfc_optimize_namespace (ns);
+
sym = ns->proc_name;
/* Check that the frontend isn't still using this. */
! { dg-do run }
! { dg-options "-O -fdump-tree-original" }
! PR 40628 - optimize unnecessary TRIMs on assignment
program main
character(len=3) :: a
character(len=4) :: b,c
b = 'abcd'
a = trim(b)
c = trim(trim(a))
if (a /= 'abc') call abort
if (c /= 'abc') call abort
end program main
! { dg-final { scan-tree-dump-times "memmove" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
/* Optimize statements on expressions, using gfc.
Copyright (C) 2010 Free Software Foundation, Inc.
Contributed by Thomas König
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This contains files for a front end optimizer. */
#include "config.h"
#include "system.h"
#include "gfortran.h"
#include "arith.h"
/* Forward declarations. */
static void strip_function_call (gfc_expr *);
static void optimize_assignment (gfc_code *);
/* Go through all executable statements of a namespace, invoking
specific optimizations along the way. */
void gfc_optimize_namespace (gfc_namespace * ns)
{
gfc_code * c;
for (c = ns->code; c; c = c->next)
{
switch (c->op)
{
case EXEC_ASSIGN:
optimize_assignment (c);
default:
break;
}
}
}
/* Do the optimizations for assignments. This function calls itself
recursively for any successes. */
static void
optimize_assignment (gfc_code * c)
{
gfc_expr *lhs, *rhs;
lhs = c->expr1;
rhs = c->expr2;
/* Optimize away a = trim(b), where a is a character variable. */
if (lhs->ts.type == BT_CHARACTER)
{
if (rhs->expr_type == EXPR_FUNCTION &&
rhs->value.function.isym &&
rhs->value.function.isym->id == GFC_ISYM_TRIM)
{
strip_function_call (rhs);
optimize_assignment (c);
}
}
}
/* Remove an unneeded function call, modifying the expression.
This replaces the function call with the value of its
first argument. The rest of the argument list is freed. */
static void
strip_function_call (gfc_expr *e)
{
gfc_expr *e1;
gfc_actual_arglist *a;
a = e->value.function.actual;
/* We should have at least one argument. */
gcc_assert (a->expr != NULL);
e1 = a->expr;
/* Free the remaining arglist, if any. */
if (a->next)
gfc_free_actual_arglist (a->next);
/* Graft the argument expression onto the original function. */
*e = *e1;
gfc_free (e1);
}