aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Koenig <koenigni@student.ethz.ch>2020-11-29 14:40:31 +0100
committerNicolas Koenig <koenigni@student.ethz.ch>2020-11-29 14:40:31 +0100
commit660f011333a1c0709bec953f0940bb85a4f62773 (patch)
tree271772645dff5d1b88dc9801f16125bf1f13bc55
parent00c2e5d1c15c67fc2c9d9ed86bfa1f5aa13848cc (diff)
downloadgcc-660f011333a1c0709bec953f0940bb85a4f62773.zip
gcc-660f011333a1c0709bec953f0940bb85a4f62773.tar.gz
gcc-660f011333a1c0709bec953f0940bb85a4f62773.tar.bz2
Fix offset calculation.
-rw-r--r--gcc/fortran/trans-array.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 1a75bb5..ec350c3 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2962,17 +2962,23 @@ cas_add_strides (tree expr, tree desc, int beg, int end)
}
-/* This function calculates the new offset via
+/* If the full offset is needed, this function calculates the new offset via
new_offset = offset
+ (this_image () + lbound[first_codim] - 1)*stride[first_codim]
+ sum (stride[i]*lbound[i]) over remaining codim
+ If the offset is computed by other means, and we just need to get rid of
+ the coarray part, it is calculated via
+
+ new_offset = offset
+ + (this_image () - 1)*stride[first_codim]
+
If offset is a pointer, we also need to multiply it by the size. */
static tree
cas_add_this_image_offset (tree offset, tree desc, gfc_array_ref *ar,
- int is_pointer)
+ int is_pointer, bool has_full_offset)
{
tree tmp, off;
/* Calculate the actual offset. */
@@ -2982,10 +2988,11 @@ cas_add_this_image_offset (tree offset, tree desc, gfc_array_ref *ar,
tmp = convert (TREE_TYPE (gfc_index_zero_node), tmp);
/* tmp = _gfortran_cas_coarray_this_image (0) - 1 */
tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
- build_int_cst (TREE_TYPE (tmp), 1));
+ build_int_cst (TREE_TYPE (tmp), 1));
/* tmp = _gfortran_cas_coarray_this_image (0) - 1 + lbound[first_codim] */
- tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp), tmp,
- gfc_conv_array_lbound(desc, ar->dimen));
+ if (has_full_offset)
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp), tmp,
+ gfc_conv_array_lbound(desc, ar->dimen));
/* tmp = (_gfortran_cas_coarray_this_image (0) - 1 + lbound[first_codim])
* stride(first_codim). */
tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
@@ -2993,8 +3000,12 @@ cas_add_this_image_offset (tree offset, tree desc, gfc_array_ref *ar,
/* We also need to add the missing strides once to compensate for the
offset, that is to large now. The loop starts at sym->as.rank+1
because we need to skip the first corank stride. */
- off = cas_add_strides (tmp, desc, ar->as->rank + 1,
- ar->as->rank + ar->as->corank);
+ if (has_full_offset)
+ off = cas_add_strides (tmp, desc, ar->as->rank + 1,
+ ar->as->rank + ar->as->corank);
+ else
+ off = tmp;
+
if (is_pointer)
{
/* Remove pointer and array from type in order to get the raw base type. */
@@ -3081,7 +3092,7 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
{
gfc_ref *co_ref = cas_array_ref (ref);
if (co_ref)
- tmp = cas_add_this_image_offset (tmp, se.expr,&co_ref->u.ar, 1);
+ tmp = cas_add_this_image_offset (tmp, se.expr,&co_ref->u.ar, 1, 1);
}
/* If this is a variable or address of a variable we use it directly.
Otherwise we must evaluate it now to avoid breaking dependency
@@ -3881,7 +3892,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
}
if (flag_coarray == GFC_FCOARRAY_SHARED && need_impl_this_image)
- offset = cas_add_this_image_offset (offset, se->expr, ar, 0);
+ offset = cas_add_this_image_offset (offset, se->expr, ar, 0, 1);
if (!integer_zerop (cst_offset))
offset = fold_build2_loc (input_location, PLUS_EXPR,
@@ -7114,7 +7125,7 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
{
gfc_ref *co_ref = cas_array_ref (expr->ref);
if (co_ref)
- offset = cas_add_this_image_offset (offset, desc, &co_ref->u.ar, 0);
+ offset = cas_add_this_image_offset (offset, desc, &co_ref->u.ar, 0, 0);
}
tmp = build_array_ref (desc, offset, NULL, NULL);