This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);

}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]