diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-04-01 19:16:01 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-04-01 19:16:01 +0000 |
commit | a6c8790e53319b084d29d398027376b912a77ebc (patch) | |
tree | ad78eafeef59122c479f9d41d9f9949909ac0226 /gcc/fortran/dependency.c | |
parent | 4d4677fd775aada7c8b69f0ad3493a1a901f4c3f (diff) | |
download | gcc-a6c8790e53319b084d29d398027376b912a77ebc.tar.gz |
* dependency.c (gfc_is_inside_range): Delete.
(gfc_check_element_vs_section): Significant rewrite.
* gfortran.dg/dependencency_17.f90: New test case.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112607 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/dependency.c')
-rw-r--r-- | gcc/fortran/dependency.c | 147 |
1 files changed, 101 insertions, 46 deletions
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c index c3762bdc4d8..f664ec0d0f8 100644 --- a/gcc/fortran/dependency.c +++ b/gcc/fortran/dependency.c @@ -858,70 +858,125 @@ gfc_check_section_vs_section (gfc_ref * lref, gfc_ref * rref, int n) } -/* Checks if the expr chk is inside the range left-right. - Returns GFC_DEP_NODEP if chk is outside the range, - GFC_DEP_OVERLAP otherwise. - Assumes left<=right. */ +/* Determines overlapping for a single element and a section. */ static gfc_dependency -gfc_is_inside_range (gfc_expr * chk, gfc_expr * left, gfc_expr * right) +gfc_check_element_vs_section( gfc_ref * lref, gfc_ref * rref, int n) { - int l; - int r; + gfc_array_ref *ref; + gfc_expr *elem; + gfc_expr *start; + gfc_expr *end; + gfc_expr *stride; int s; - s = gfc_dep_compare_expr (left, right); - if (s == -2) + elem = lref->u.ar.start[n]; + if (!elem) return GFC_DEP_OVERLAP; - l = gfc_dep_compare_expr (chk, left); - r = gfc_dep_compare_expr (chk, right); + ref = &rref->u.ar; + start = ref->start[n] ; + end = ref->end[n] ; + stride = ref->stride[n]; + + if (!start && IS_ARRAY_EXPLICIT (ref->as)) + start = ref->as->lower[n]; + if (!end && IS_ARRAY_EXPLICIT (ref->as)) + end = ref->as->upper[n]; + + /* Determine whether the stride is positive or negative. */ + if (!stride) + s = 1; + else if (stride->expr_type == EXPR_CONSTANT + && stride->ts.type == BT_INTEGER) + s = mpz_sgn (stride->value.integer); + else + s = -2; - /* Check for indeterminate relationships. */ - if (l == -2 || r == -2 || s == -2) + /* Stride should never be zero. */ + if (s == 0) return GFC_DEP_OVERLAP; + /* Positive strides. */ if (s == 1) { - /* When left>right we want to check for right <= chk <= left. */ - if (l <= 0 || r >= 0) - return GFC_DEP_OVERLAP; + /* Check for elem < lower. */ + if (start && gfc_dep_compare_expr (elem, start) == -1) + return GFC_DEP_NODEP; + /* Check for elem > upper. */ + if (end && gfc_dep_compare_expr (elem, end) == 1) + return GFC_DEP_NODEP; + + if (start && end) + { + s = gfc_dep_compare_expr (start, end); + /* Check for an empty range. */ + if (s == 1) + return GFC_DEP_NODEP; + if (s == 0 && gfc_dep_compare_expr (elem, start) == 0) + return GFC_DEP_EQUAL; + } + } + /* Negative strides. */ + else if (s == -1) + { + /* Check for elem > upper. */ + if (end && gfc_dep_compare_expr (elem, start) == 1) + return GFC_DEP_NODEP; + /* Check for elem < lower. */ + if (start && gfc_dep_compare_expr (elem, end) == -1) + return GFC_DEP_NODEP; + + if (start && end) + { + s = gfc_dep_compare_expr (start, end); + /* Check for an empty range. */ + if (s == -1) + return GFC_DEP_NODEP; + if (s == 0 && gfc_dep_compare_expr (elem, start) == 0) + return GFC_DEP_EQUAL; + } } + /* Unknown strides. */ else { - /* Otherwise check for left <= chk <= right. */ - if (l >= 0 || r <= 0) + if (!start || !end) return GFC_DEP_OVERLAP; + s = gfc_dep_compare_expr (start, end); + if (s == -2) + return GFC_DEP_OVERLAP; + /* Assume positive stride. */ + if (s == -1) + { + /* Check for elem < lower. */ + if (gfc_dep_compare_expr (elem, start) == -1) + return GFC_DEP_NODEP; + /* Check for elem > upper. */ + if (gfc_dep_compare_expr (elem, end) == 1) + return GFC_DEP_NODEP; + } + /* Assume negative stride. */ + else if (s == 1) + { + /* Check for elem > upper. */ + if (gfc_dep_compare_expr (elem, start) == 1) + return GFC_DEP_NODEP; + /* Check for elem < lower. */ + if (gfc_dep_compare_expr (elem, end) == -1) + return GFC_DEP_NODEP; + } + /* Equal bounds. */ + else if (s == 0) + { + s = gfc_dep_compare_expr (elem, start); + if (s == 0) + return GFC_DEP_EQUAL; + if (s == 1 || s == -1) + return GFC_DEP_NODEP; + } } - - return GFC_DEP_NODEP; -} - -/* Determines overlapping for a single element and a section. */ - -static gfc_dependency -gfc_check_element_vs_section( gfc_ref * lref, gfc_ref * rref, int n) -{ - gfc_array_ref l_ar; - gfc_array_ref r_ar; - gfc_expr *l_start; - gfc_expr *r_start; - gfc_expr *r_end; - - l_ar = lref->u.ar; - r_ar = rref->u.ar; - l_start = l_ar.start[n] ; - r_start = r_ar.start[n] ; - r_end = r_ar.end[n] ; - if (NULL == r_start && IS_ARRAY_EXPLICIT (r_ar.as)) - r_start = r_ar.as->lower[n]; - if (NULL == r_end && IS_ARRAY_EXPLICIT (r_ar.as)) - r_end = r_ar.as->upper[n]; - if (NULL == r_start || NULL == r_end || l_start == NULL) - return GFC_DEP_OVERLAP; - - return gfc_is_inside_range (l_start, r_end, r_start); + return GFC_DEP_OVERLAP; } |