This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[Fortran] Yet more array dependence improvements
- From: Roger Sayle <roger at eyesopen dot com>
- To: fortran at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 9 Mar 2006 16:18:57 -0700 (MST)
- Subject: [Fortran] Yet more array dependence improvements
I'm still working on the patch to catch FORALL indices in scalar
array references (to fix dependency_9.f90 and the recent polyhedron
regressions), but the following "simple" dependency improvement
should help improve things in the mean-time.
There's currently an interesting difference between the front-end
dependencies detected on 32-bit and 64-bit platforms. Consider
the following code (taken from dependency_10.f90 below).
integer, dimension (4) :: a
integer :: n
n = 3
where (a(:n) .ne. 0)
a(:n) = 1
endwhere
One i686-pc-linux-gnu, we correctly detect that "a(:n)" is the
same as "a(:n)", however on x86_64-unknown-linux-gnu, we don't,
and instead allocate a temporary array!
The problem is that array indices are different widths/types on
different targets, so on 64-bit machines the gfortran front-end
inserts a call to __gfc_convert_i4_i8 in the upper bound of the
array section. This unfortunately is enough to trip up the routine
gfc_dep_compare_expr, which assumes the worst, and we therefore
treat these refs as overlaping.
The patch below extends gfc_dep_compare_expr, to be able to test
the equality of intrinsic operators/functions depending upon
whether their operands/arguments are considered equal. Hence
we assume __gfc_convert_i4_i8(x) is the equal to __gfc_convert_i4_i8(y)
if we can show that x is equal to y. Likewise, because it's easy/common
we also handle unary and binary operators, so that we can tell
"n + 1" == "n + 1", when "n" == "n" and "1" == "1".
The patch below has been tested on x86_64-unknown-linux-gnu with a
full "make bootstrap", including gfortran, and regression tested
with a top-level "make -k check" with no new failures. Both new
tests pass with this patch, though dependency_10.f90 passed previously
on IA-32, but not x86_64. [dependency_11.f90 failed everywhere].
Hopefully, this should benefit real-world code, as the idiom
"array(:n)" is commonly used for dealing with variable numbers of
elements in fixed sized arrays. For example, polyhedron's
protein.f90 (sp?) uses "array(:natoms)" in its' WHERE statements.
Ok for mainline?
2003-03-09 Roger Sayle <roger@eyesopen.com>
* dependency.c (gfc_dep_compare_expr) <EXPR_OP>: Allow unary and
binary operators to compare equal if their operands are equal.
<EXPR_FUNCTION>: Allow "constant" intrinsic conversion functions
to compare equal, if their operands are equal.
* gfortran.dg/dependency_10.f90: New test case.
* gfortran.dg/dependency_11.f90: Likewise.
Index: dependency.c
===================================================================
*** dependency.c (revision 111839)
--- dependency.c (working copy)
*************** gfc_dep_compare_expr (gfc_expr * e1, gfc
*** 97,102 ****
--- 97,153 ----
return 0;
return -2;
+ case EXPR_OP:
+ /* Intrinsic operators are the same if their operands are the same. */
+ if (e1->value.op.operator != e2->value.op.operator)
+ return -2;
+ if (e1->value.op.op2 == 0)
+ {
+ i = gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op1);
+ return i == 0 ? 0 : -2;
+ }
+ if (gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op1) == 0
+ && gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op2) == 0)
+ return 0;
+ /* TODO Handle commutative binary operators here? */
+ return -2;
+
+ case EXPR_FUNCTION:
+ /* We can only compare calls to the same intrinsic function. */
+ if (e1->value.function.isym == 0
+ || e2->value.function.isym == 0
+ || e1->value.function.isym != e2->value.function.isym)
+ return -2;
+
+ /* We should list the "constant" intrinsic functions. Those
+ without side-effects that provide equal results given equal
+ argument lists. */
+ switch (e1->value.function.isym->generic_id)
+ {
+ case GFC_ISYM_CONVERSION:
+ case GFC_ISYM_REAL:
+ case GFC_ISYM_LOGICAL:
+ case GFC_ISYM_DBLE:
+ break;
+
+ default:
+ return -2;
+ }
+
+ /* Compare the argument lists for equality. */
+ {
+ gfc_actual_arglist *args1 = e1->value.function.actual;
+ gfc_actual_arglist *args2 = e2->value.function.actual;
+ while (args1 && args2)
+ {
+ if (gfc_dep_compare_expr (args1->expr, args2->expr) != 0)
+ return -2;
+ args1 = args1->next;
+ args2 = args2->next;
+ }
+ return (args1 || args2) ? -2 : 0;
+ }
+
default:
return -2;
}
! { dg-do compile }
! { dg-options "-O2 -fdump-tree-original" }
subroutine foo(a)
integer, dimension (4) :: a
integer :: n
n = 3
where (a(:n) .ne. 0)
a(:n) = 1
endwhere
end subroutine
! { dg-final { scan-tree-dump-times "malloc" 0 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
! { dg-do compile }
! { dg-options "-O2 -fdump-tree-original" }
subroutine foo(a)
integer, dimension (4) :: a
integer :: n
n = 3
where (a(:n-1) .ne. 0)
a(:n-1) = 1
endwhere
end subroutine
! { dg-final { scan-tree-dump-times "malloc" 0 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
Roger
--