Hello world,

this patch fixes the performance regression introduced with
the fix for 71783.  It also corrects an error in the logic
in realloc_string_callback by now checking if the experssion
is deferred, instead of checking for the symbol having the
allocatable attribute (which led to false positives).

It also checks for the presence of a substring on the RHS
expression, because the problem cannot happen if there is
no RHS substring.

Regression-tested on trunk.

OK for trunk?  Also OK for a backport?

Regards

        Thomas

2016-08-14  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/71902
        * frontend-passes.c (realloc_string_callback):  Check for deferred
on the expression instead for allocatable on the symbol. Name temporary
        variable "realloc_string".

2016-08-14  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/71902
        * gfortran.dg/dependency_47.f90:  New test.
Index: frontend-passes.c
===================================================================
--- frontend-passes.c	(Revision 239218)
+++ frontend-passes.c	(Arbeitskopie)
@@ -164,6 +164,7 @@ realloc_string_callback (gfc_code **c, int *walk_s
   gfc_expr *expr1, *expr2;
   gfc_code *co = *c;
   gfc_expr *n;
+  gfc_ref *ref;
 
   if (co->op != EXEC_ASSIGN)
     return 0;
@@ -170,7 +171,7 @@ realloc_string_callback (gfc_code **c, int *walk_s
 
   expr1 = co->expr1;
   if (expr1->ts.type != BT_CHARACTER || expr1->rank != 0
-      || !expr1->symtree->n.sym->attr.allocatable)
+      || !expr1->ts.deferred)
     return 0;
 
   expr2 = gfc_discard_nops (co->expr2);
@@ -177,6 +178,13 @@ realloc_string_callback (gfc_code **c, int *walk_s
   if (expr2->expr_type != EXPR_VARIABLE)
     return 0;
 
+  /* Only substring expressions can be affected; substrings are always the
+   last reference.  */
+
+  for (ref = expr2->ref; ref; ref = ref->next)
+    if (ref->type != REF_SUBSTRING)
+      return 0;
+
   if (!gfc_check_dependency (expr1, expr2, true))
     return 0;
 
@@ -190,7 +198,7 @@ realloc_string_callback (gfc_code **c, int *walk_s
   current_code = c;
   inserted_block = NULL;
   changed_statement = NULL;
-  n = create_var (expr2, "trim");
+  n = create_var (expr2, "realloc_string");
   co->expr2 = n;
   return 0;
 }
! { dg-do compile }
! Make sure there is only one instance of a temporary variable here.
! { dg-options "-fdump-tree-original" }

SUBROUTINE prtdata(ilen)
  INTEGER :: ilen
  character(len=ilen), allocatable :: cline(:)
  allocate(cline(2))
  cline(1) = 'a'
  cline(1)(2:3) = cline(1)(1:2)
  cline(2) = cline(1)
  print *,c
END SUBROUTINE prtdata
! { dg-final { scan-tree-dump-not "__var_" "original" } }

Reply via email to