This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]