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] Improved dependency analysis of pointer variables


The following patch improves the gfortran front-end's dependency analysis
of array expressions containing pointer variables.  The first change is
to shuffle around the tests of "pointerness" such that we only check
whether expr1 is a pointer when comparing EXPR_VARIABLEs.  At the moment,
we'll mistakenly consider that "p = 0" contains a dependency, even though
the RHS (expr2) is constant, just because the LHS (expr1) is "pointer"
variable.

The second change is that we now allow pointer variables to be considered
equal, so that "p" and "p" (variable expressions of the same symbol) are
treated as referencing the same object, even when "p" is a pointer type.

Finally, the third change is that a pointer variable "p" and another
variable "v" can not reference the same object, if the base type of
"p" is not the same as the base type of "v".  To demonstrate this
consider the example code below extracted from the polyhedron benchmark
capacita.f90:


    integer, private, pointer, dimension(:,:) :: Grid
    real, allocatable, dimension(:,:) :: Y

    where (Grid == 0)
      Y = 0
    end where


The WHERE statement looks quite trivial; we test one variable Grid
as a mask, to conditionally set another variable Y.  Unfortunately,
mainline currently allocates a temporary LOGICAL*1 mask as it believes
that writes to Y may affect the values of Grid!?  The problem is that
Grid is defined as a pointer which currently pessimizes the dependency
checking in gfc_check_dependency.  Of course, looking closer there
couldn't possibly be a dependency using type-based aliasing, as Grid
points to an array of integers and Y points to an array of reals.
The Fortran standards guarantee that these two references can't alias,
as is supported by the comments in symbol.c:gfc_symbols_could_alias.


The following patch has been tested on x86_64-unknown-linux-gnu with
a full "make bootstrap", including fortran, and regression tested with
a top-level "make -k check" with no new failures.  Note this patch
doesn't conflict with or depend upon my other pending dependency.c
change.

Ok for mainline?



2006-03-15  Roger Sayle  <roger@eyesopen.com>

	* dependency.c (gfc_check_dependency): Improve handling of pointers;
	Two variables of different types can't have a dependency, and two
	variables with the same symbol are equal, even if pointers.

	* gfortran.dg/dependency_12.f90: New test case.


Index: dependency.c
===================================================================
*** dependency.c	(revision 112052)
--- dependency.c	(working copy)
*************** gfc_check_dependency (gfc_expr * expr1,
*** 472,486 ****

    gcc_assert (expr1->expr_type == EXPR_VARIABLE);

-   /* TODO: -fassume-no-pointer-aliasing */
-   if (expr1->symtree->n.sym->attr.pointer)
-     return 1;
-   for (ref = expr1->ref; ref; ref = ref->next)
-     {
-       if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
- 	return 1;
-     }
-
    switch (expr2->expr_type)
      {
      case EXPR_OP:
--- 472,477 ----
*************** gfc_check_dependency (gfc_expr * expr1,
*** 492,512 ****
        return 0;

      case EXPR_VARIABLE:
!       if (expr2->symtree->n.sym->attr.pointer)
! 	return 1;
!
!       for (ref = expr2->ref; ref; ref = ref->next)
  	{
! 	  if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
  	    return 1;
- 	}

!       /* Return 1 if expr1 and expr2 are equivalenced arrays.  */
!       if (gfc_are_equivalenced_arrays (expr1, expr2))
! 	return 1;

!       if (expr1->symtree->n.sym != expr2->symtree->n.sym)
! 	return 0;

        if (identical)
  	return 1;
--- 483,526 ----
        return 0;

      case EXPR_VARIABLE:
!       /* The interesting cases are when the symbols don't match.  */
!       if (expr1->symtree->n.sym != expr2->symtree->n.sym)
  	{
! 	  gfc_typespec *ts1 = &expr1->symtree->n.sym->ts;
! 	  gfc_typespec *ts2 = &expr2->symtree->n.sym->ts;
!
! 	  /* Return 1 if expr1 and expr2 are equivalenced arrays.  */
! 	  if (gfc_are_equivalenced_arrays (expr1, expr2))
  	    return 1;

! 	  /* Symbols can only alias if they have the same type.  */
! 	  if (ts1->type != BT_UNKNOWN
! 	      && ts2->type != BT_UNKNOWN
! 	      && ts1->type != BT_DERIVED
! 	      && ts2->type != BT_DERIVED)
! 	    {
! 	      if (ts1->type != ts2->type
! 		  || ts1->kind != ts2->kind)
! 		return 0;
! 	    }

! 	  /* If either variable is a pointer, assume the worst.  */
! 	  /* TODO: -fassume-no-pointer-aliasing */
! 	  if (expr1->symtree->n.sym->attr.pointer)
! 	    return 1;
! 	  for (ref = expr1->ref; ref; ref = ref->next)
! 	    if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
! 	      return 1;
!
! 	  if (expr2->symtree->n.sym->attr.pointer)
! 	    return 1;
! 	  for (ref = expr2->ref; ref; ref = ref->next)
! 	    if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
! 	      return 1;
!
! 	  /* Otherwise distinct symbols have no dependencies.  */
! 	  return 0;
! 	}

        if (identical)
  	return 1;



! { dg-do compile }
! { dg-options "-O2 -fdump-tree-original" }
subroutine foo(a,b)
  integer, pointer, dimension (:,:) :: a
  real, dimension(:,:) :: b

  where (a == 0)
    b = 0.0
  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]