diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2019-01-07 19:30:28 +0000 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2019-01-07 19:30:28 +0000 |
commit | 419af57c134f3b068530ea51179c220e52623067 (patch) | |
tree | 13b595e197309edb81f16d4d5476a620191f51b9 /gcc/fortran/expr.c | |
parent | 25a34b0236ffcf23e9bc29826475729ccfef7c38 (diff) | |
download | gcc-419af57c134f3b068530ea51179c220e52623067.zip gcc-419af57c134f3b068530ea51179c220e52623067.tar.gz gcc-419af57c134f3b068530ea51179c220e52623067.tar.bz2 |
re PR fortran/45424 ([F08] Add IS_CONTIGUOUS intrinsic)
2019-01-07 Thomas Koenig <tkoenig@gcc.gnu.org>
Harald Anlauf <anlauf@gmx.de>
Tobias Burnus <burnus@gcc.gnu.org>
PR fortran/45424
* check.c (gfc_check_is_contiguous): New function.
* expr.c (gfc_is_not_contiguous): New function.
* gfortran.h (gfc_isym_id): Add GFC_ISYM_IS_CONTIGUOUS.
Add prototype for gfc_is_not_contiguous.
* intrinsic.c (do_ts29113_check): Add GFC_ISYM_IS_CONTIGUOUS.
(add_function): Add is_contiguous.
* intrinsic.h: Add prototypes for gfc_check_is_contiguous,
gfc_simplify_is_contiguous and gfc_resolve_is_contiguous.
* intrinsic.texi: Add IS_CONTIGUOUS.
* iresolve.c (gfc_resolve_is_contiguous): New function.
* simplify.c (gfc_simplify_is_contiguous): New function.
* trans-decl.c (gfor_fncecl_is_contiguous0): New variable.
(gfc_build_intrinsic_function_decl): Add it.
* trans-intrinsic.c (gfc_conv_intrinsic_is_contiguous): New
function.
(gfc_conv_intrinsic_function): Handle GFC_ISYM_IS_CONTIGUOUS.
2019-01-07 Thomas Koenig <tkoenig@gcc.gnu.org>
Harald Anlauf <anlauf@gmx.de>
Tobias Burnus <burnus@gcc.gnu.org>
PR fortran/45424
* Makefile.am: Add intrinsics/is_contiguous.c.
* Makefile.in: Regenerated.
* gfortran.map: Add _gfortran_is_contiguous0.
* intrinsics/is_contiguous.c: New file.
* libgfortran.h: Add prototype for is_contiguous0.
2019-01-07 Thomas Koenig <tkoenig@gcc.gnu.org>
Harald Anlauf <anlauf@gmx.de>
Tobias Burnus <burnus@gcc.gnu.org>
* gfortran.dg/is_contiguous_1.f90: New test.
* gfortran.dg/is_contiguous_2.f90: New test.
* gfortran.dg/is_contiguous_3.f90: New test.
Co-Authored-By: Harald Anlauf <anlauf@gmx.de>
Co-Authored-By: Tobias Burnus <burnus@gcc.gnu.org>
From-SVN: r267657
Diffstat (limited to 'gcc/fortran/expr.c')
-rw-r--r-- | gcc/fortran/expr.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 7d1c65d..cd8d4dd 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -5695,6 +5695,75 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict, bool permit_element) return true; } +/* Return true if the expression is guaranteed to be non-contiguous, + false if we cannot prove anything. It is probably best to call + this after gfc_is_simply_contiguous. If neither of them returns + true, we cannot say (at compile-time). */ + +bool +gfc_is_not_contiguous (gfc_expr *array) +{ + int i; + gfc_array_ref *ar = NULL; + gfc_ref *ref; + bool previous_incomplete; + + for (ref = array->ref; ref; ref = ref->next) + { + /* Array-ref shall be last ref. */ + + if (ar) + return true; + + if (ref->type == REF_ARRAY) + ar = &ref->u.ar; + } + + if (ar == NULL || ar->type != AR_SECTION) + return false; + + previous_incomplete = false; + + /* Check if we can prove that the array is not contiguous. */ + + for (i = 0; i < ar->dimen; i++) + { + mpz_t arr_size, ref_size; + + if (gfc_ref_dimen_size (ar, i, &ref_size, NULL)) + { + if (gfc_dep_difference (ar->as->lower[i], ar->as->upper[i], &arr_size)) + { + /* a(2:4,2:) is known to be non-contiguous, but + a(2:4,i:i) can be contiguous. */ + if (previous_incomplete && mpz_cmp_si (ref_size, 1) != 0) + { + mpz_clear (arr_size); + mpz_clear (ref_size); + return true; + } + else if (mpz_cmp (arr_size, ref_size) != 0) + previous_incomplete = true; + + mpz_clear (arr_size); + } + + /* Check for a(::2), i.e. where the stride is not unity. + This is only done if there is more than one element in + the reference along this dimension. */ + + if (mpz_cmp_ui (ref_size, 1) > 0 && ar->type == AR_SECTION + && ar->dimen_type[i] == DIMEN_RANGE + && ar->stride[i] && ar->stride[i]->expr_type == EXPR_CONSTANT + && mpz_cmp_si (ar->stride[i]->value.integer, 1) != 0) + return true; + + mpz_clear (ref_size); + } + } + /* We didn't find anything definitive. */ + return false; +} /* Build call to an intrinsic procedure. The number of arguments has to be passed (rather than ending the list with a NULL value) because we may |