This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch, fortran] Fix PR 86837, wrong code regression in implied do loop in i/o
- From: Thomas König <tk at tkoenig dot net>
- To: "fortran at gcc dot gnu dot org" <fortran at gcc dot gnu dot org>, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 23 Aug 2018 22:12:09 +0200
- Subject: [patch, fortran] Fix PR 86837, wrong code regression in implied do loop in i/o
Hello world,
this patch fixes a regression by correctly checking that
the innner start, step or end values of an implied do
loop do not depend on an outer loop variable.
The check was actually done before, but gfc_check_dependency
wasn't finding all relevant cases.
Regression-tested. OK for trunk and 8.x?
Regards
Thomas
2018-08-23 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/86837
* frontend-passes.c (var_in_expr_callback): New function.
(var_in_expr): New function.
(traverse_io_block): Use var_in_expr instead of
gfc_check_dependency for checking if the variable depends on the
previous interators.
2018-08-23 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/86837
* gfortran.dg/implied_do_io_6.f90: New test.
Index: frontend-passes.c
===================================================================
--- frontend-passes.c (Revision 263752)
+++ frontend-passes.c (Arbeitskopie)
@@ -1104,6 +1104,31 @@ convert_elseif (gfc_code **c, int *walk_subtrees A
return 0;
}
+/* Callback function to var_in_expr - return true if expr1 and
+ expr2 are identical variables. */
+static int
+var_in_expr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ gfc_expr *expr1 = (gfc_expr *) data;
+ gfc_expr *expr2 = *e;
+
+ if (expr2->expr_type != EXPR_VARIABLE)
+ return 0;
+
+ return expr1->symtree->n.sym == expr2->symtree->n.sym;
+}
+
+/* Return true if expr1 is found in expr2. */
+
+static bool
+var_in_expr (gfc_expr *expr1, gfc_expr *expr2)
+{
+ gcc_assert (expr1->expr_type == EXPR_VARIABLE);
+
+ return gfc_expr_walker (&expr2, var_in_expr_callback, (void *) expr1);
+}
+
struct do_stack
{
struct do_stack *prev;
@@ -1256,9 +1281,9 @@ traverse_io_block (gfc_code *code, bool *has_reach
for (int j = i - 1; j < i; j++)
{
if (iters[j]
- && (gfc_check_dependency (var, iters[j]->start, true)
- || gfc_check_dependency (var, iters[j]->end, true)
- || gfc_check_dependency (var, iters[j]->step, true)))
+ && (var_in_expr (var, iters[j]->start)
+ || var_in_expr (var, iters[j]->end)
+ || var_in_expr (var, iters[j]->step)))
return false;
}
}
! { dg-do run }
! { dg-options "-ffrontend-optimize" }
! PR 86837 - this was mis-optimized by trying to turn this into an
! array I/O statement.
! Original test case by "Pascal".
Program read_loop
implicit none
integer :: i, j
! number of values per column
integer, dimension(3) :: nvalues
data nvalues / 1, 2, 4 /
! values in a 1D array
real, dimension(7) :: one_d
data one_d / 1, 11, 12, 21, 22, 23, 24 /
! where to store the data back
real, dimension(4, 3) :: two_d
! 1 - write our 7 values in one block
open(unit=10, file="loop.dta", form="unformatted")
write(10) one_d
close(unit=10)
! 2 - read them back in chosen cells of a 2D array
two_d = -9
open(unit=10, file="loop.dta", form="unformatted", status='old')
read(10) ((two_d(i,j), i=1,nvalues(j)), j=1,3)
close(unit=10, status='delete')
! 4 - print the whole array, just in case
if (any(reshape(two_d,[12]) /= [1.,-9.,-9.,-9.,11.,12.,-9.,-9.,21.,22.,23.,24.])) call abort
end Program read_loop