Beispiel #1
0
int
gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
{
  int n;
  gfc_dependency fin_dep;
  gfc_dependency this_dep;

  this_dep = GFC_DEP_ERROR;
  fin_dep = GFC_DEP_ERROR;
  /* Dependencies due to pointers should already have been identified.
     We only need to check for overlapping array references.  */

  while (lref && rref)
    {
      /* We're resolving from the same base symbol, so both refs should be
	 the same type.  We traverse the reference chain until we find ranges
	 that are not equal.  */
      gcc_assert (lref->type == rref->type);
      switch (lref->type)
	{
	case REF_COMPONENT:
	  /* The two ranges can't overlap if they are from different
	     components.  */
	  if (lref->u.c.component != rref->u.c.component)
	    return 0;
	  break;
	  
	case REF_SUBSTRING:
	  /* Substring overlaps are handled by the string assignment code
	     if there is not an underlying dependency.  */
	  return (fin_dep == GFC_DEP_OVERLAP) ? 1 : 0;
	
	case REF_ARRAY:

	  if (ref_same_as_full_array (lref, rref))
	    return 0;

	  if (ref_same_as_full_array (rref, lref))
	    return 0;

	  if (lref->u.ar.dimen != rref->u.ar.dimen)
	    {
	      if (lref->u.ar.type == AR_FULL)
		fin_dep = gfc_full_array_ref_p (rref, NULL) ? GFC_DEP_EQUAL
							    : GFC_DEP_OVERLAP;
	      else if (rref->u.ar.type == AR_FULL)
		fin_dep = gfc_full_array_ref_p (lref, NULL) ? GFC_DEP_EQUAL
							    : GFC_DEP_OVERLAP;
	      else
		return 1;
	      break;
	    }

	  for (n=0; n < lref->u.ar.dimen; n++)
	    {
	      /* Assume dependency when either of array reference is vector
		 subscript.  */
	      if (lref->u.ar.dimen_type[n] == DIMEN_VECTOR
		  || rref->u.ar.dimen_type[n] == DIMEN_VECTOR)
		return 1;

	      if (lref->u.ar.dimen_type[n] == DIMEN_RANGE
		  && rref->u.ar.dimen_type[n] == DIMEN_RANGE)
		this_dep = gfc_check_section_vs_section (lref, rref, n);
	      else if (lref->u.ar.dimen_type[n] == DIMEN_ELEMENT
		       && rref->u.ar.dimen_type[n] == DIMEN_RANGE)
		this_dep = gfc_check_element_vs_section (lref, rref, n);
	      else if (rref->u.ar.dimen_type[n] == DIMEN_ELEMENT
		       && lref->u.ar.dimen_type[n] == DIMEN_RANGE)
		this_dep = gfc_check_element_vs_section (rref, lref, n);
	      else 
		{
		  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 any dimension doesn't overlap, we have no dependency.  */
	      if (this_dep == GFC_DEP_NODEP)
		return 0;

	      /* Now deal with the loop reversal logic:  This only works on
		 ranges and is activated by setting
				reverse[n] == GFC_CAN_REVERSE
		 The ability to reverse or not is set by previous conditions
		 in this dimension.  If reversal is not activated, the
		 value GFC_DEP_BACKWARD is reset to GFC_DEP_OVERLAP.  */
	      if (rref->u.ar.dimen_type[n] == DIMEN_RANGE
		    && lref->u.ar.dimen_type[n] == DIMEN_RANGE)
		{
		  /* Set reverse if backward dependence and not inhibited.  */
		  if (reverse && reverse[n] != GFC_CANNOT_REVERSE)
		    reverse[n] = (this_dep == GFC_DEP_BACKWARD) ?
			         GFC_REVERSE_SET : reverse[n];

		  /* Inhibit loop reversal if dependence not compatible.  */
		  if (reverse && reverse[n] != GFC_REVERSE_NOT_SET
		        && this_dep != GFC_DEP_EQUAL
		        && this_dep != GFC_DEP_BACKWARD
		        && this_dep != GFC_DEP_NODEP)
		    {
	              reverse[n] = GFC_CANNOT_REVERSE;
		      if (this_dep != GFC_DEP_FORWARD)
			this_dep = GFC_DEP_OVERLAP;
		    }

		  /* If no intention of reversing or reversing is explicitly
		     inhibited, convert backward dependence to overlap.  */
		  if ((reverse == NULL && this_dep == GFC_DEP_BACKWARD)
			|| (reverse && reverse[n] == GFC_CANNOT_REVERSE))
		    this_dep = GFC_DEP_OVERLAP;
		}

	      /* Overlap codes are in order of priority.  We only need to
		 know the worst one.*/
	      if (this_dep > fin_dep)
		fin_dep = this_dep;
	    }

	  /* If this is an equal element, we have to keep going until we find
	     the "real" array reference.  */
	  if (lref->u.ar.type == AR_ELEMENT
		&& rref->u.ar.type == AR_ELEMENT
		&& fin_dep == GFC_DEP_EQUAL)
	    break;

	  /* Exactly matching and forward overlapping ranges don't cause a
	     dependency.  */
	  if (fin_dep < GFC_DEP_BACKWARD)
	    return 0;

	  /* Keep checking.  We only have a dependency if
	     subsequent references also overlap.  */
	  break;

	default:
	  gcc_unreachable ();
	}
      lref = lref->next;
      rref = rref->next;
    }

  /* 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)
    return 1;

  return fin_dep == GFC_DEP_OVERLAP;
}
int
gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref)
{
    int n;
    gfc_dependency fin_dep;
    gfc_dependency this_dep;

    fin_dep = GFC_DEP_ERROR;
    /* Dependencies due to pointers should already have been identified.
       We only need to check for overlapping array references.  */

    while (lref && rref)
    {
        /* We're resolving from the same base symbol, so both refs should be
        the same type.  We traverse the reference chain until we find ranges
         that are not equal.  */
        gcc_assert (lref->type == rref->type);
        switch (lref->type)
        {
        case REF_COMPONENT:
            /* The two ranges can't overlap if they are from different
               components.  */
            if (lref->u.c.component != rref->u.c.component)
                return 0;
            break;

        case REF_SUBSTRING:
            /* Substring overlaps are handled by the string assignment code
               if there is not an underlying dependency.  */
            return (fin_dep == GFC_DEP_OVERLAP) ? 1 : 0;

        case REF_ARRAY:

            if (ref_same_as_full_array (lref, rref))
                return 0;

            if (ref_same_as_full_array (rref, lref))
                return 0;

            if (lref->u.ar.dimen != rref->u.ar.dimen)
            {
                if (lref->u.ar.type == AR_FULL)
                    fin_dep = gfc_full_array_ref_p (rref, NULL) ? GFC_DEP_EQUAL
                              : GFC_DEP_OVERLAP;
                else if (rref->u.ar.type == AR_FULL)
                    fin_dep = gfc_full_array_ref_p (lref, NULL) ? GFC_DEP_EQUAL
                              : GFC_DEP_OVERLAP;
                else
                    return 1;
                break;
            }

            for (n=0; n < lref->u.ar.dimen; n++)
            {
                /* Assume dependency when either of array reference is vector
                subscript.  */
                if (lref->u.ar.dimen_type[n] == DIMEN_VECTOR
                        || rref->u.ar.dimen_type[n] == DIMEN_VECTOR)
                    return 1;
                if (lref->u.ar.dimen_type[n] == DIMEN_RANGE
                        && rref->u.ar.dimen_type[n] == DIMEN_RANGE)
                    this_dep = gfc_check_section_vs_section (lref, rref, n);
                else if (lref->u.ar.dimen_type[n] == DIMEN_ELEMENT
                         && rref->u.ar.dimen_type[n] == DIMEN_RANGE)
                    this_dep = gfc_check_element_vs_section (lref, rref, n);
                else if (rref->u.ar.dimen_type[n] == DIMEN_ELEMENT
                         && lref->u.ar.dimen_type[n] == DIMEN_RANGE)
                    this_dep = gfc_check_element_vs_section (rref, lref, n);
                else
                {
                    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 any dimension doesn't overlap, we have no dependency.  */
                if (this_dep == GFC_DEP_NODEP)
                    return 0;

                /* Overlap codes are in order of priority.  We only need to
                know the worst one.*/
                if (this_dep > fin_dep)
                    fin_dep = this_dep;
            }

            /* If this is an equal element, we have to keep going until we find
               the "real" array reference.  */
            if (lref->u.ar.type == AR_ELEMENT
                    && rref->u.ar.type == AR_ELEMENT
                    && fin_dep == GFC_DEP_EQUAL)
                break;

            /* Exactly matching and forward overlapping ranges don't cause a
               dependency.  */
            if (fin_dep < GFC_DEP_OVERLAP)
                return 0;

            /* Keep checking.  We only have a dependency if
               subsequent references also overlap.  */
            break;

        default:
            gcc_unreachable ();
        }
        lref = lref->next;
        rref = rref->next;
    }

    /* 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)
        return 1;

    return fin_dep == GFC_DEP_OVERLAP;
}