re PR fortran/65819 (overzealous checking in gfc_check_dependency for identical=true)
authorThomas Koenig <tkoenig@gcc.gnu.org>
Thu, 25 Jul 2019 16:24:00 +0000 (16:24 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Thu, 25 Jul 2019 16:24:00 +0000 (16:24 +0000)
2019-07-25  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/65819
* dependency.h (gfc_dep_resovler): Add optional argument identical.
* dependency.c (gfc_check_dependency): Do not alway return 1 if
the symbol is the same. Pass on identical to gfc_dep_resolver.
(gfc_check_element_vs_element): Whitespace fix.
(gfc_dep_resolver): Adjust comment for function.  If identical is
true, return 1 if any overlap has been found.

2019-07-25  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/65819
* gfortran.dg/dependency_54.f90: New test.

From-SVN: r273807

gcc/fortran/ChangeLog
gcc/fortran/dependency.c
gcc/fortran/dependency.h
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/dependency_54.f90 [new file with mode: 0644]

index 622f576..faca1a0 100644 (file)
@@ -1,3 +1,13 @@
+2019-07-25  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/65819
+       * dependency.h (gfc_dep_resovler): Add optional argument identical.
+       * dependency.c (gfc_check_dependency): Do not alway return 1 if
+       the symbol is the same. Pass on identical to gfc_dep_resolver.
+       (gfc_check_element_vs_element): Whitespace fix.
+       (gfc_dep_resolver): Adjust comment for function.  If identical is
+       true, return 1 if any overlap has been found.
+
 2019-07-23  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/54072
@@ -6,7 +16,7 @@
        (gfc_check_transfer): Use to arguments.
        (gfc_check_storage_size): Ditto.
        (gfc_check_complex): Remove leftover comment from BOZ patch.
-       * primary.c (match_boz_constant): Remove leftover comment. 
+       * primary.c (match_boz_constant): Remove leftover comment.
 
 2019-07-23  Steven G. Kargl  <kargl@gcc.gnu.org>
 
@@ -19,7 +29,7 @@
        (match_complex_constant: Use convert_complex.
        * arith.h (gfc_convert_integer, gfc_convert_real, gfc_convert_complex):
        Remove prototypes.
-       * array.c (match_array_cons_element): A BOZ cannot be a data 
+       * array.c (match_array_cons_element): A BOZ cannot be a data
        statement value.  Jump to a common exit point.
        * check.c (gfc_invalid_boz): New function.  Emit error or warning
        for a BOZ in an invalid context.
@@ -32,7 +42,7 @@
        constant to INTEGER in accordance to F2018.
        (gfc_check_achar, gfc_check_char, gfc_check_float): Use gfc_invalid_boz.  Convert BOZ
        as needed.
-       (gfc_check_bge_bgt_ble_blt): Enforce F2018 requirements on BGE, 
+       (gfc_check_bge_bgt_ble_blt): Enforce F2018 requirements on BGE,
        BGT, BLE, and BLT intrinsic functions.
        (gfc_check_cmplx): Re-organize to check kind, if present, first.
        Convert BOZ real and/or imaginary parts as needed in accordance to
@@ -41,7 +51,7 @@
        (gfc_check_dcmplx, gfc_check_dble ): Convert BOZ as needed.
        (gfc_check_dshift):  Make dshift[lr] conform to F2018 standard.
        gfc_check_float (gfc_expr *a)
-       (gfc_check_iand_ieor_ior):  Make IAND, IEOR, and IOR conform to 
+       (gfc_check_iand_ieor_ior):  Make IAND, IEOR, and IOR conform to
        F2018 standard.
        (gfc_check_int): Conform to F2018 standard.
        (gfc_check_intconv): Deprecate SHORT and LONG aliases for INT2 and
@@ -62,7 +72,7 @@
        INTEGER or REAL.
        * gfortran.h (gfc_expr): Add a boz component.  Remove is_boz component.
        (gfc_boz2int, gfc_boz2real, gfc_invalid_boz): New prototypes.
-       * interface.c (gfc_extend_assign): Guard against replacing an 
+       * interface.c (gfc_extend_assign): Guard against replacing an
        intrinsic involving a BOZ literal constant on RHS.
        * invoke.texi: Doument -fallow-invalid-boz.
        * lang.opt: New option. -fallow-invalid-boz.
index be330e2..da4a37c 100644 (file)
@@ -1351,13 +1351,10 @@ gfc_check_dependency (gfc_expr *expr1, gfc_expr *expr2, bool identical)
          return 0;
        }
 
-      if (identical)
-       return 1;
-
       /* Identical and disjoint ranges return 0,
         overlapping ranges return 1.  */
       if (expr1->ref && expr2->ref)
-       return gfc_dep_resolver (expr1->ref, expr2->ref, NULL);
+       return gfc_dep_resolver (expr1->ref, expr2->ref, NULL, identical);
 
       return 1;
 
@@ -1884,6 +1881,7 @@ gfc_check_element_vs_element (gfc_ref *lref, gfc_ref *rref, int n)
 
   if (i > -2)
     return GFC_DEP_NODEP;
+
   return GFC_DEP_EQUAL;
 }
 
@@ -2084,13 +2082,15 @@ ref_same_as_full_array (gfc_ref *full_ref, gfc_ref *ref)
 
 /* Finds if two array references are overlapping or not.
    Return value
-       2 : array references are overlapping but reversal of one or
+       2 : array references are overlapping but reversal of one or
            more dimensions will clear the dependency.
-       1 : array references are overlapping.
-       0 : array references are identical or not overlapping.  */
+       1 : array references are overlapping, or identical is true and
+           there is some kind of overlap.
+       0 : array references are identical or not overlapping.  */
 
 int
-gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
+gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse,
+                 bool identical)
 {
   int n;
   int m;
@@ -2124,11 +2124,15 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
 
        case REF_ARRAY:
 
+         /* For now, treat all coarrays as dangerous.  */
+         if (lref->u.ar.codimen || rref->u.ar.codimen)
+           return 1;
+
          if (ref_same_as_full_array (lref, rref))
-           return 0;
+           return identical;
 
          if (ref_same_as_full_array (rref, lref))
-           return 0;
+           return identical;
 
          if (lref->u.ar.dimen != rref->u.ar.dimen)
            {
@@ -2180,6 +2184,8 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
                  gcc_assert (rref->u.ar.dimen_type[n] == DIMEN_ELEMENT
                              && lref->u.ar.dimen_type[n] == DIMEN_ELEMENT);
                  this_dep = gfc_check_element_vs_element (rref, lref, n);
+                 if (identical && this_dep == GFC_DEP_EQUAL)
+                   this_dep = GFC_DEP_OVERLAP;
                }
 
              /* If any dimension doesn't overlap, we have no dependency.  */
@@ -2240,6 +2246,9 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
                 know the worst one.*/
 
            update_fin_dep:
+             if (identical && this_dep == GFC_DEP_EQUAL)
+               this_dep = GFC_DEP_OVERLAP;
+
              if (this_dep > fin_dep)
                fin_dep = this_dep;
            }
@@ -2253,7 +2262,7 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
 
          /* Exactly matching and forward overlapping ranges don't cause a
             dependency.  */
-         if (fin_dep < GFC_DEP_BACKWARD)
+         if (fin_dep < GFC_DEP_BACKWARD && !identical)
            return 0;
 
          /* Keep checking.  We only have a dependency if
@@ -2267,11 +2276,14 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
       rref = rref->next;
     }
 
+  /* Assume the worst if we nest to different depths.  */
+  if (lref || rref)
+    return 1;
+
   /* If we haven't seen any array refs then something went wrong.  */
   gcc_assert (fin_dep != GFC_DEP_ERROR);
 
-  /* Assume the worst if we nest to different depths.  */
-  if (lref || rref)
+  if (identical && fin_dep != GFC_DEP_NODEP)
     return 1;
 
   return fin_dep == GFC_DEP_OVERLAP;
index dd30887..eca60f7 100644 (file)
@@ -37,7 +37,8 @@ int gfc_check_fncall_dependency (gfc_expr *, sym_intent, gfc_symbol *,
 int gfc_check_dependency (gfc_expr *, gfc_expr *, bool);
 int gfc_expr_is_one (gfc_expr *, int);
 
-int gfc_dep_resolver(gfc_ref *, gfc_ref *, gfc_reverse *);
+int gfc_dep_resolver (gfc_ref *, gfc_ref *, gfc_reverse *,
+                     bool identical = false);
 int gfc_are_equivalenced_arrays (gfc_expr *, gfc_expr *);
 
 gfc_expr * gfc_discard_nops (gfc_expr *);
index 948acc0..ea5d239 100644 (file)
@@ -1,3 +1,8 @@
+2019-07-25  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/65819
+       * gfortran.dg/dependency_54.f90: New test.
+
 2019-07-25  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/case_optimization3.ad[sb]: New test.
diff --git a/gcc/testsuite/gfortran.dg/dependency_54.f90 b/gcc/testsuite/gfortran.dg/dependency_54.f90
new file mode 100644 (file)
index 0000000..f738ed8
--- /dev/null
@@ -0,0 +1,24 @@
+! { dg-do  run }
+! { dg-additional-options "-fdump-tree-original -ffrontend-optimize" }
+! PR 65819 - this used to cause a temporary in matmul inlining.
+! Check that these are absent by looking for the names of the
+! temporary variables.
+program main
+  implicit none
+  real, dimension(3,3,3) :: f
+  real, dimension(3,3) :: res
+  real, dimension(2,3,3) :: backup
+  integer :: three
+  integer :: i
+
+  data f(1,:,:) /9*-42./
+  data f(2:3,:,:) /2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61/
+  data res /652, 772, 984, 2010, 2406, 3082, 3402, 4086, 5242/ 
+  three = 3
+  backup = f(2:3,:,:)
+  f(1, 1:three, :) = matmul(f(2,1:3,2:3), f(3,2:3,:))
+  if (any (res /= f(1,:,:))) stop 1
+  if (any (f(2:3,:,:) /= backup)) stop 2
+end program main
+! { dg-final { scan-tree-dump-not "mma" "original" } }
+! { dg-final { scan-tree-dump-not "mmb" "original" } }