From patchwork Mon Dec 27 19:19:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Koenig X-Patchwork-Id: 76799 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A85FFB70D4 for ; Tue, 28 Dec 2010 06:20:45 +1100 (EST) Received: (qmail 28056 invoked by alias); 27 Dec 2010 19:20:08 -0000 Received: (qmail 27987 invoked by uid 22791); 27 Dec 2010 19:20:00 -0000 X-SWARE-Spam-Status: No, hits=2.1 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_JMF_BL, TW_FC, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from cc-smtpout2.netcologne.de (HELO cc-smtpout2.netcologne.de) (89.1.8.212) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 27 Dec 2010 19:19:52 +0000 Received: from cc-smtpin2.netcologne.de (cc-smtpin2.netcologne.de [89.1.8.202]) by cc-smtpout2.netcologne.de (Postfix) with ESMTP id 5B321123B4; Mon, 27 Dec 2010 20:19:46 +0100 (CET) Received: from [192.168.0.197] (xdsl-78-35-164-42.netcologne.de [78.35.164.42]) by cc-smtpin2.netcologne.de (Postfix) with ESMTPA id 2F43811E8F; Mon, 27 Dec 2010 20:19:45 +0100 (CET) Subject: [patch, fortran] PR 46065 - optimize trim From: Thomas Koenig To: fortran@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org Date: Mon, 27 Dec 2010 20:19:44 +0100 Message-ID: <1293477584.3714.24.camel@linux-fd1f.site> Mime-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello world, the attached patch changes trim(a) into a(1:len_trim(a)), thus eliminating the need for a temporary. The patch is rather straightforward, and should be rather safe. This is a bit of speed and memory use improvement that I would still like to see in 4.6. Regression-tested. OK for trunk? Thomas 2010-12-27 Thomas Koenig PR fortran/47065 * frontend-passes.c (optimize_trim): New function. (optimize_expr): Call it. 2010-12-27 Thomas Koenig PR fortran/47065 * gfortran.dg/optimize_trim_3.f90: New test. Index: frontend-passes.c =================================================================== --- frontend-passes.c (Revision 168201) +++ frontend-passes.c (Arbeitskopie) @@ -34,6 +34,7 @@ static void optimize_namespace (gfc_namespace *); 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 *); /* Entry point - run all passes for a namespace. So far, only an optimization pass is run. */ @@ -68,6 +69,10 @@ static int optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED) { + + if (optimize_trim (*e)) + gfc_simplify_expr (*e, 0); + if ((*e)->expr_type == EXPR_OP && optimize_op (*e)) gfc_simplify_expr (*e, 0); return 0; @@ -395,6 +400,70 @@ optimize_comparison (gfc_expr *e, gfc_intrinsic_op return false; } +/* Optimize a trim function by replacing it with an equivalent substring + involving a call to len_trim. This only works for expressions where + variables are trimmed. Return true if anything was modified. */ + +static bool +optimize_trim (gfc_expr *e) +{ + gfc_expr *a; + gfc_ref *ref; + gfc_expr *fcn; + gfc_actual_arglist *actual_arglist, *next; + + if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION + || e->value.function.isym == NULL + || e->value.function.isym->id != GFC_ISYM_TRIM) + return false; + + a = e->value.function.actual->expr; + + if (a->expr_type != EXPR_VARIABLE) + return false; + + 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; + } + else + { + strip_function_call (e); + + /* Create the reference. */ + + ref = gfc_get_ref (); + ref->type = REF_SUBSTRING; + + /* Set the start of the reference. */ + + ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); + + /* Build the function call to len_trim(x, gfc_defaul_integer_kind). */ + + 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; + e->ref = ref; + return true; + } +} + #define WALK_SUBEXPR(NODE) \ do \ { \