* [Patch, Fortran] Support allocatable *scalar* coarrays
@ 2011-07-10 21:16 Tobias Burnus
2011-07-11 7:54 ` Tobias Burnus
0 siblings, 1 reply; 10+ messages in thread
From: Tobias Burnus @ 2011-07-10 21:16 UTC (permalink / raw)
To: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 958 bytes --]
This patch implemented the trans*.c part of allocatable scalar coarrays;
contrary to noncoarray allocatable scalars, they have cobounds and thus
use an array descriptor.
While there are still some bugs and minor omissions, gfortran slowly
gets feature compile with regards to single-image coarrays support.
Still to be done: Fixes to LOCK_TYPE constraint checks, polymorphic
coarrays, some issues with coarray dummies, some issues with allocatable
coarray components.
The patch also works with -fcoarray=lib. However, the to-do list for
libcaf is much longer. On the front-end side, there are additional
issues with argument passing, deallocate, some minor allocate issues
("token"), and in particular calling the library for actual
communication, for locking and for atomic access. Additionally, the
message-processing loop in the library is still missing.
The attached patch was build and regtested on x86-64-linux.
OK for the trunk?
Tobias
[-- Attachment #2: caf_alloc_scalar.diff --]
[-- Type: text/x-patch, Size: 16052 bytes --]
2011-07-10 Tobias Burnus <burnus@net-b.de>
* expr.c (gfc_ref_this_image): New function.
(gfc_is_coindexed): Use it.
* gfortran.h (gfc_ref_this_image): New prototype.
* resolve.c (resolve_deallocate_expr,
resolve_allocate_expr): Support alloc scalar coarrays.
* trans-array.c (gfc_conv_array_ref, gfc_array_init_size,
gfc_conv_descriptor_cosize, gfc_array_allocate,
gfc_trans_deferred_array): Ditto.
* trans-expr.c (gfc_conv_variable) Ditto.:
* trans-stmt.c (gfc_trans_deallocate): Ditto.
* trans-types.c (gfc_get_element_type, gfc_get_array_type_bounds
gfc_get_array_descr_info): Ditto.
2011-07-10 Tobias Burnus <burnus@net-b.de>
* gfortran.dg/coarray_14.f90: Remove dg-error "sorry not implemented".
* gfortran.dg/coarray_7.f90: Ditto.
* gfortran.dg/coarray/scalar_alloc_1.f90: New.
* gfortran.dg/coarray/scalar_alloc_2.f90: New.
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 6db0836..3bf1e94 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4126,18 +4126,28 @@ gfc_expr_replace_comp (gfc_expr *expr, gfc_component *dest)
bool
+gfc_ref_this_image (gfc_ref *ref)
+{
+ int n;
+
+ gcc_assert (ref->type == REF_ARRAY && ref->u.ar.codimen > 0);
+
+ for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++)
+ if (ref->u.ar.dimen_type[n] != DIMEN_THIS_IMAGE)
+ return false;
+
+ return true;
+}
+
+
+bool
gfc_is_coindexed (gfc_expr *e)
{
gfc_ref *ref;
for (ref = e->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
- {
- int n;
- for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++)
- if (ref->u.ar.dimen_type[n] != DIMEN_THIS_IMAGE)
- return true;
- }
+ return !gfc_ref_this_image (ref);
return false;
}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 328dfbe..eb01b0e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2733,6 +2733,7 @@ void gfc_expr_replace_comp (gfc_expr *, gfc_component *);
bool gfc_is_proc_ptr_comp (gfc_expr *, gfc_component **);
+bool gfc_ref_this_image (gfc_ref *ref);
bool gfc_is_coindexed (gfc_expr *);
int gfc_get_corank (gfc_expr *);
bool gfc_has_ultimate_allocatable (gfc_expr *);
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index b51ae96..07104b8 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -6460,7 +6460,9 @@ resolve_deallocate_expr (gfc_expr *e)
switch (ref->type)
{
case REF_ARRAY:
- if (ref->u.ar.type != AR_FULL)
+ if (ref->u.ar.type != AR_FULL
+ && !(ref->u.ar.type == AR_ELEMENT && ref->u.ar.as->rank == 0
+ && ref->u.ar.codimen && gfc_ref_this_image (ref)))
allocatable = 0;
break;
@@ -6983,13 +6985,6 @@ check_symbols:
goto failure;
}
- if (codimension && ar->as->rank == 0)
- {
- gfc_error ("Sorry, allocatable scalar coarrays are not yet supported "
- "at %L", &e->where);
- goto failure;
- }
-
success:
return SUCCESS;
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index f4f79f9..4ec892b 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2623,12 +2623,20 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
if (ar->dimen == 0)
{
gcc_assert (ar->codimen);
- if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
- && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
- se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
- /* Use the actual tree type and not the wrapped coarray. */
- se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)), se->expr);
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
+ se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
+ else
+ {
+ if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
+ && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
+ se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
+
+ /* Use the actual tree type and not the wrapped coarray. */
+ se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
+ se->expr);
+ }
+
return;
}
@@ -4139,7 +4147,11 @@ gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
stride = stride * size;
}
+ for (n = rank; n < rank+corank; n++)
+ (Set lcobound/ucobound as above.)
element_size = sizeof (array element);
+ if (!rank)
+ return element_size
stride = (size_t) stride;
overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
stride = stride * element_size;
@@ -4309,6 +4321,10 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
/* Convert to size_t. */
element_size = fold_convert (size_type_node, tmp);
+
+ if (rank == 0)
+ return element_size;
+
stride = fold_convert (size_type_node, stride);
/* First check for overflow. Since an array of type character can
@@ -4370,18 +4386,18 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
{
tree tmp;
tree pointer;
- tree offset;
+ tree offset = NULL_TREE;
tree size;
tree msg;
- tree error;
+ tree error = NULL_TREE;
tree overflow; /* Boolean storing whether size calculation overflows. */
- tree var_overflow;
+ tree var_overflow = NULL_TREE;
tree cond;
stmtblock_t elseblock;
gfc_expr **lower;
gfc_expr **upper;
gfc_ref *ref, *prev_ref = NULL;
- bool allocatable, coarray;
+ bool allocatable, coarray, dimension;
ref = expr->ref;
@@ -4401,20 +4417,17 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
{
allocatable = expr->symtree->n.sym->attr.allocatable;
coarray = expr->symtree->n.sym->attr.codimension;
+ dimension = expr->symtree->n.sym->attr.dimension;
}
else
{
allocatable = prev_ref->u.c.component->attr.allocatable;
coarray = prev_ref->u.c.component->attr.codimension;
+ dimension = prev_ref->u.c.component->attr.dimension;
}
- /* Return if this is a scalar coarray. */
- if ((!prev_ref && !expr->symtree->n.sym->attr.dimension)
- || (prev_ref && !prev_ref->u.c.component->attr.dimension))
- {
- gcc_assert (coarray);
- return false;
- }
+ if (!dimension)
+ gcc_assert (coarray);
/* Figure out the size of the array. */
switch (ref->u.ar.type)
@@ -4449,16 +4462,20 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
ref->u.ar.as->corank, &offset, lower, upper,
&se->pre, &overflow);
+ if (dimension)
+ {
- var_overflow = gfc_create_var (integer_type_node, "overflow");
- gfc_add_modify (&se->pre, var_overflow, overflow);
+ var_overflow = gfc_create_var (integer_type_node, "overflow");
+ gfc_add_modify (&se->pre, var_overflow, overflow);
- /* Generate the block of code handling overflow. */
- msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const
+ /* Generate the block of code handling overflow. */
+ msg = gfc_build_addr_expr (pchar_type_node,
+ gfc_build_localized_cstring_const
("Integer overflow when calculating the amount of "
"memory to allocate"));
- error = build_call_expr_loc (input_location,
- gfor_fndecl_runtime_error, 1, msg);
+ error = build_call_expr_loc (input_location, gfor_fndecl_runtime_error,
+ 1, msg);
+ }
if (pstat != NULL_TREE && !integer_zerop (pstat))
{
@@ -4495,14 +4512,20 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
gfc_add_expr_to_block (&elseblock, tmp);
- cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- var_overflow, integer_zero_node));
- tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
- error, gfc_finish_block (&elseblock));
+ if (dimension)
+ {
+ cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
+ boolean_type_node, var_overflow, integer_zero_node));
+ tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ error, gfc_finish_block (&elseblock));
+ }
+ else
+ tmp = gfc_finish_block (&elseblock);
gfc_add_expr_to_block (&se->pre, tmp);
- gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
+ if (dimension)
+ gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
&& expr->ts.u.derived->attr.alloc_comp)
@@ -7446,7 +7469,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
gfc_add_expr_to_block (&cleanup, tmp);
}
- if (sym->attr.allocatable && sym->attr.dimension
+ if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
&& !sym->attr.save && !sym->attr.result)
{
tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 7383265..55a0fc4 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -691,8 +691,9 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
}
else if (!sym->attr.value)
{
- /* Dereference non-character scalar dummy arguments. */
- if (sym->attr.dummy && !sym->attr.dimension)
+ /* Dereference non-character scalar dummy arguments. */
+ if (sym->attr.dummy && !sym->attr.dimension
+ && !(sym->attr.codimension && sym->attr.allocatable))
se->expr = build_fold_indirect_ref_loc (input_location,
se->expr);
@@ -711,7 +712,8 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
&& (sym->attr.dummy
|| sym->attr.function
|| sym->attr.result
- || !sym->attr.dimension))
+ || (!sym->attr.dimension
+ && (!sym->attr.codimension || !sym->attr.allocatable))))
se->expr = build_fold_indirect_ref_loc (input_location,
se->expr);
}
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 88fdcd1..5aa0ca9 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5104,7 +5104,7 @@ gfc_trans_deallocate (gfc_code *code)
se.descriptor_only = 1;
gfc_conv_expr (&se, expr);
- if (expr->rank)
+ if (expr->rank || gfc_expr_attr (expr).codimension)
{
if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
{
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 6d384be..d7f1dd5 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1125,8 +1125,9 @@ gfc_get_element_type (tree type)
gcc_assert (TREE_CODE (element) == POINTER_TYPE);
element = TREE_TYPE (element);
- gcc_assert (TREE_CODE (element) == ARRAY_TYPE);
- element = TREE_TYPE (element);
+ /* For arrays, which are not scalar coarrays. */
+ if (TREE_CODE (element) == ARRAY_TYPE)
+ element = TREE_TYPE (element);
}
return element;
@@ -1770,6 +1771,16 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
/* TODO: known offsets for descriptors. */
GFC_TYPE_ARRAY_OFFSET (fat_type) = NULL_TREE;
+ if (dimen == 0)
+ {
+ arraytype = build_pointer_type (etype);
+ if (restricted)
+ arraytype = build_qualified_type (arraytype, TYPE_QUAL_RESTRICT);
+
+ GFC_TYPE_ARRAY_DATAPTR_TYPE (fat_type) = arraytype;
+ return fat_type;
+ }
+
/* We define data as an array with the correct size if possible.
Much better than doing pointer arithmetic. */
if (stride)
@@ -2835,8 +2846,11 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
gcc_assert (POINTER_TYPE_P (etype));
etype = TREE_TYPE (etype);
- gcc_assert (TREE_CODE (etype) == ARRAY_TYPE);
- etype = TREE_TYPE (etype);
+
+ /* If the type is not a scalar coarray. */
+ if (TREE_CODE (etype) == ARRAY_TYPE)
+ etype = TREE_TYPE (etype);
+
/* Can't handle variable sized elements yet. */
if (int_size_in_bytes (etype) <= 0)
return false;
diff --git a/gcc/testsuite/gfortran.dg/coarray_14.f90 b/gcc/testsuite/gfortran.dg/coarray_14.f90
index 3e3f046..49188d6 100644
--- a/gcc/testsuite/gfortran.dg/coarray_14.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_14.f90
@@ -49,7 +49,7 @@ type t
end type t
type(t), allocatable :: a[:]
allocate (t :: a) ! { dg-error "Coarray specification required in ALLOCATE statement" }
-allocate (t :: a[*]) ! { dg-error "allocatable scalar coarrays are not yet supported" }
+allocate (t :: a[*]) ! OK
end program myTest
! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_7.f90 b/gcc/testsuite/gfortran.dg/coarray_7.f90
index 29af0d1..abbd64d 100644
--- a/gcc/testsuite/gfortran.dg/coarray_7.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_7.f90
@@ -90,7 +90,7 @@ type(t), allocatable :: b(:)[:], C[:]
allocate(b(1)) ! { dg-error "Coarray specification" }
allocate(a[3]%a(5)) ! { dg-error "Coindexed allocatable" }
-allocate(c[*]) ! { dg-error "Sorry" }
+allocate(c[*]) ! OK
allocate(a%a(5)) ! OK
end subroutine alloc
@@ -151,9 +151,9 @@ subroutine allocateTest()
integer :: n, q
n = 1
q = 1
- allocate(a[q,*]) ! { dg-error "Sorry" }
- allocate(b[q,*]) ! { dg-error "Sorry" }
- allocate(c[q,*]) ! { dg-error "Sorry" }
+ allocate(a[q,*]) ! OK
+ allocate(b[q,*]) ! OK
+ allocate(c[q,*]) ! OK
end subroutine allocateTest
--- /dev/null 2011-07-10 08:01:05.659884893 +0200
+++ gcc/gcc/testsuite/gfortran.dg/coarray/scalar_alloc_1.f90 2011-07-10 20:22:18.000000000 +0200
@@ -0,0 +1,50 @@
+! { dg-do run }
+!
+implicit none
+integer, allocatable :: A[:], B[:,:]
+integer :: n1, n2, n3
+
+if (allocated (a)) call abort ()
+if (allocated (b)) call abort ()
+
+allocate(a[*])
+a = 5 + this_image ()
+if (a[this_image ()] /= 5 + this_image ()) call abort
+
+a[this_image ()] = 8 - 2*this_image ()
+if (a[this_image ()] /= 8 - 2*this_image ()) call abort
+
+if (lcobound(a, dim=1) /= 1 .or. ucobound(a,dim=1) /= num_images()) &
+ call abort ()
+deallocate(a)
+
+allocate(a[4:*])
+a[this_image ()] = 8 - 2*this_image ()
+
+if (lcobound(a, dim=1) /= 4 .or. ucobound(a,dim=1) /= 3 + num_images()) &
+ call abort ()
+
+n1 = -1
+n2 = 5
+n3 = 3
+allocate (B[n1:n2, n3:*])
+if (any (lcobound(b) /= [-1, 3]) .or. lcobound(B, dim=2) /= n3) &
+ call abort()
+call sub(A, B)
+
+if (allocated (a)) call abort ()
+if (.not.allocated (b)) call abort ()
+
+! automatically deallocate "B"
+contains
+ subroutine sub(x, y)
+ integer, allocatable :: x[:], y[:,:]
+
+ if (any (lcobound(y) /= [-1, 3]) .or. lcobound(y, dim=2) /= n3) &
+ call abort()
+ if (lcobound(x, dim=1) /= 4 .or. ucobound(x,dim=1) /= 3 + num_images()) &
+ call abort ()
+ if (x[this_image ()] /= 8 - 2*this_image ()) call abort
+ deallocate(x)
+ end subroutine sub
+end
--- /dev/null 2011-07-10 08:01:05.659884893 +0200
+++ gcc/gcc/testsuite/gfortran.dg/coarray/scalar_alloc_2.f90 2011-07-10 20:18:11.000000000 +0200
@@ -0,0 +1,60 @@
+! { dg-do run }
+!
+! Check whether registering allocatable coarrays works
+!
+type position
+ real :: x, y, z
+end type position
+
+integer, allocatable :: a[:]
+type(position), allocatable :: p[:]
+
+allocate(a[*])
+a = 7
+
+allocate(p[*])
+p%x = 11
+p%y = 13
+p%z = 15
+
+if (a /= 7) call abort()
+a = 88
+if (a /= 88) call abort()
+
+if (p%x /= 11) call abort()
+p%x = 17
+if (p%x /= 17) call abort()
+
+ block
+ integer, allocatable :: b[:]
+
+ allocate(b[*])
+ b = 8494
+
+ if (b /= 8494) call abort()
+ end block
+
+if (a /= 88) call abort()
+call test ()
+end
+
+subroutine test()
+ type velocity
+ real :: x, y, z
+ end type velocity
+
+ real, allocatable :: z[:]
+ type(velocity), allocatable :: v[:]
+
+ allocate(z[*])
+ z = sqrt(2.0)
+
+ allocate(v[*])
+ v%x = 21
+ v%y = 23
+ v%z = 25
+
+ if (z /= sqrt(2.0)) call abort()
+ if (v%x /= 21) call abort()
+
+end subroutine test
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-10 21:16 [Patch, Fortran] Support allocatable *scalar* coarrays Tobias Burnus
@ 2011-07-11 7:54 ` Tobias Burnus
2011-07-14 7:38 ` *ping* - " Tobias Burnus
2011-07-16 14:38 ` Mikael Morin
0 siblings, 2 replies; 10+ messages in thread
From: Tobias Burnus @ 2011-07-11 7:54 UTC (permalink / raw)
To: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 488 bytes --]
On 07/10/2011 09:56 PM, Tobias Burnus wrote:
> This patch implemented the trans*.c part of allocatable scalar
> coarrays; contrary to noncoarray allocatable scalars, they have
> cobounds and thus use an array descriptor.
I found a test case (part of Reinhold Bader's fortran_tests), which gave
an ICE: Allocatable scalar coarrays with SAVE.
I have fixed that (trans-decl.c) and added a test.
> The attached patch was build and regtested on x86-64-linux.
> OK for the trunk?
Tobias
[-- Attachment #2: caf_alloc_scalar-v2.diff --]
[-- Type: text/x-patch, Size: 17644 bytes --]
2011-07-11 Tobias Burnus <burnus@net-b.de>
* expr.c (gfc_ref_this_image): New function.
(gfc_is_coindexed): Use it.
* gfortran.h (gfc_ref_this_image): New prototype.
* resolve.c (resolve_deallocate_expr,
resolve_allocate_expr): Support alloc scalar coarrays.
* trans-array.c (gfc_conv_array_ref, gfc_array_init_size,
gfc_conv_descriptor_cosize, gfc_array_allocate,
gfc_trans_deferred_array): Ditto.
* trans-expr.c (gfc_conv_variable) Ditto.:
* trans-stmt.c (gfc_trans_deallocate): Ditto.
* trans-types.c (gfc_get_element_type, gfc_get_array_type_bounds
gfc_get_array_descr_info): Ditto.
* trans-decl.c (gfc_get_symbol_decl): Ditto.
2011-07-11 Tobias Burnus <burnus@net-b.de>
* gfortran.dg/coarray_14.f90: Remove dg-error "sorry not implemented".
* gfortran.dg/coarray_7.f90: Ditto.
* gfortran.dg/coarray/scalar_alloc_1.f90: New.
* gfortran.dg/coarray/scalar_alloc_2.f90: New.
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 6db0836..3bf1e94 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4126,18 +4126,28 @@ gfc_expr_replace_comp (gfc_expr *expr, gfc_component *dest)
bool
+gfc_ref_this_image (gfc_ref *ref)
+{
+ int n;
+
+ gcc_assert (ref->type == REF_ARRAY && ref->u.ar.codimen > 0);
+
+ for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++)
+ if (ref->u.ar.dimen_type[n] != DIMEN_THIS_IMAGE)
+ return false;
+
+ return true;
+}
+
+
+bool
gfc_is_coindexed (gfc_expr *e)
{
gfc_ref *ref;
for (ref = e->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
- {
- int n;
- for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++)
- if (ref->u.ar.dimen_type[n] != DIMEN_THIS_IMAGE)
- return true;
- }
+ return !gfc_ref_this_image (ref);
return false;
}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 328dfbe..eb01b0e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2733,6 +2733,7 @@ void gfc_expr_replace_comp (gfc_expr *, gfc_component *);
bool gfc_is_proc_ptr_comp (gfc_expr *, gfc_component **);
+bool gfc_ref_this_image (gfc_ref *ref);
bool gfc_is_coindexed (gfc_expr *);
int gfc_get_corank (gfc_expr *);
bool gfc_has_ultimate_allocatable (gfc_expr *);
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index b51ae96..07104b8 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -6460,7 +6460,9 @@ resolve_deallocate_expr (gfc_expr *e)
switch (ref->type)
{
case REF_ARRAY:
- if (ref->u.ar.type != AR_FULL)
+ if (ref->u.ar.type != AR_FULL
+ && !(ref->u.ar.type == AR_ELEMENT && ref->u.ar.as->rank == 0
+ && ref->u.ar.codimen && gfc_ref_this_image (ref)))
allocatable = 0;
break;
@@ -6983,13 +6985,6 @@ check_symbols:
goto failure;
}
- if (codimension && ar->as->rank == 0)
- {
- gfc_error ("Sorry, allocatable scalar coarrays are not yet supported "
- "at %L", &e->where);
- goto failure;
- }
-
success:
return SUCCESS;
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index f4f79f9..4ec892b 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2623,12 +2623,20 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
if (ar->dimen == 0)
{
gcc_assert (ar->codimen);
- if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
- && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
- se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
- /* Use the actual tree type and not the wrapped coarray. */
- se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)), se->expr);
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
+ se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
+ else
+ {
+ if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
+ && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
+ se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
+
+ /* Use the actual tree type and not the wrapped coarray. */
+ se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
+ se->expr);
+ }
+
return;
}
@@ -4139,7 +4147,11 @@ gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
stride = stride * size;
}
+ for (n = rank; n < rank+corank; n++)
+ (Set lcobound/ucobound as above.)
element_size = sizeof (array element);
+ if (!rank)
+ return element_size
stride = (size_t) stride;
overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
stride = stride * element_size;
@@ -4309,6 +4321,10 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
/* Convert to size_t. */
element_size = fold_convert (size_type_node, tmp);
+
+ if (rank == 0)
+ return element_size;
+
stride = fold_convert (size_type_node, stride);
/* First check for overflow. Since an array of type character can
@@ -4370,18 +4386,18 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
{
tree tmp;
tree pointer;
- tree offset;
+ tree offset = NULL_TREE;
tree size;
tree msg;
- tree error;
+ tree error = NULL_TREE;
tree overflow; /* Boolean storing whether size calculation overflows. */
- tree var_overflow;
+ tree var_overflow = NULL_TREE;
tree cond;
stmtblock_t elseblock;
gfc_expr **lower;
gfc_expr **upper;
gfc_ref *ref, *prev_ref = NULL;
- bool allocatable, coarray;
+ bool allocatable, coarray, dimension;
ref = expr->ref;
@@ -4401,20 +4417,17 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
{
allocatable = expr->symtree->n.sym->attr.allocatable;
coarray = expr->symtree->n.sym->attr.codimension;
+ dimension = expr->symtree->n.sym->attr.dimension;
}
else
{
allocatable = prev_ref->u.c.component->attr.allocatable;
coarray = prev_ref->u.c.component->attr.codimension;
+ dimension = prev_ref->u.c.component->attr.dimension;
}
- /* Return if this is a scalar coarray. */
- if ((!prev_ref && !expr->symtree->n.sym->attr.dimension)
- || (prev_ref && !prev_ref->u.c.component->attr.dimension))
- {
- gcc_assert (coarray);
- return false;
- }
+ if (!dimension)
+ gcc_assert (coarray);
/* Figure out the size of the array. */
switch (ref->u.ar.type)
@@ -4449,16 +4462,20 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
ref->u.ar.as->corank, &offset, lower, upper,
&se->pre, &overflow);
+ if (dimension)
+ {
- var_overflow = gfc_create_var (integer_type_node, "overflow");
- gfc_add_modify (&se->pre, var_overflow, overflow);
+ var_overflow = gfc_create_var (integer_type_node, "overflow");
+ gfc_add_modify (&se->pre, var_overflow, overflow);
- /* Generate the block of code handling overflow. */
- msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const
+ /* Generate the block of code handling overflow. */
+ msg = gfc_build_addr_expr (pchar_type_node,
+ gfc_build_localized_cstring_const
("Integer overflow when calculating the amount of "
"memory to allocate"));
- error = build_call_expr_loc (input_location,
- gfor_fndecl_runtime_error, 1, msg);
+ error = build_call_expr_loc (input_location, gfor_fndecl_runtime_error,
+ 1, msg);
+ }
if (pstat != NULL_TREE && !integer_zerop (pstat))
{
@@ -4495,14 +4512,20 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
gfc_add_expr_to_block (&elseblock, tmp);
- cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- var_overflow, integer_zero_node));
- tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
- error, gfc_finish_block (&elseblock));
+ if (dimension)
+ {
+ cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
+ boolean_type_node, var_overflow, integer_zero_node));
+ tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ error, gfc_finish_block (&elseblock));
+ }
+ else
+ tmp = gfc_finish_block (&elseblock);
gfc_add_expr_to_block (&se->pre, tmp);
- gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
+ if (dimension)
+ gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
&& expr->ts.u.derived->attr.alloc_comp)
@@ -7446,7 +7469,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
gfc_add_expr_to_block (&cleanup, tmp);
}
- if (sym->attr.allocatable && sym->attr.dimension
+ if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
&& !sym->attr.save && !sym->attr.result)
{
tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index ddc7c36..96aefa3 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1425,7 +1425,8 @@ gfc_get_symbol_decl (gfc_symbol * sym)
&& (sym->attr.save || sym->ns->proc_name->attr.is_main_program
|| gfc_option.flag_max_stack_var_size == 0
|| sym->attr.data || sym->ns->proc_name->attr.flavor == FL_MODULE)
- && (gfc_option.coarray != GFC_FCOARRAY_LIB || !sym->attr.codimension))
+ && (gfc_option.coarray != GFC_FCOARRAY_LIB
+ || !sym->attr.codimension || sym->attr.allocatable))
{
/* Add static initializer. For procedures, it is only needed if
SAVE is specified otherwise they need to be reinitialized
@@ -1433,7 +1434,9 @@ gfc_get_symbol_decl (gfc_symbol * sym)
in this case due to -fmax-stack-var-size=. */
DECL_INITIAL (decl) = gfc_conv_initializer (sym->value, &sym->ts,
TREE_TYPE (decl),
- sym->attr.dimension,
+ sym->attr.dimension
+ || (sym->attr.codimension
+ && sym->attr.allocatable),
sym->attr.pointer
|| sym->attr.allocatable,
sym->attr.proc_pointer);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 7383265..55a0fc4 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -691,8 +691,9 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
}
else if (!sym->attr.value)
{
- /* Dereference non-character scalar dummy arguments. */
- if (sym->attr.dummy && !sym->attr.dimension)
+ /* Dereference non-character scalar dummy arguments. */
+ if (sym->attr.dummy && !sym->attr.dimension
+ && !(sym->attr.codimension && sym->attr.allocatable))
se->expr = build_fold_indirect_ref_loc (input_location,
se->expr);
@@ -711,7 +712,8 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
&& (sym->attr.dummy
|| sym->attr.function
|| sym->attr.result
- || !sym->attr.dimension))
+ || (!sym->attr.dimension
+ && (!sym->attr.codimension || !sym->attr.allocatable))))
se->expr = build_fold_indirect_ref_loc (input_location,
se->expr);
}
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 88fdcd1..5aa0ca9 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5104,7 +5104,7 @@ gfc_trans_deallocate (gfc_code *code)
se.descriptor_only = 1;
gfc_conv_expr (&se, expr);
- if (expr->rank)
+ if (expr->rank || gfc_expr_attr (expr).codimension)
{
if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
{
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 6d384be..d7f1dd5 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1125,8 +1125,9 @@ gfc_get_element_type (tree type)
gcc_assert (TREE_CODE (element) == POINTER_TYPE);
element = TREE_TYPE (element);
- gcc_assert (TREE_CODE (element) == ARRAY_TYPE);
- element = TREE_TYPE (element);
+ /* For arrays, which are not scalar coarrays. */
+ if (TREE_CODE (element) == ARRAY_TYPE)
+ element = TREE_TYPE (element);
}
return element;
@@ -1770,6 +1771,16 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
/* TODO: known offsets for descriptors. */
GFC_TYPE_ARRAY_OFFSET (fat_type) = NULL_TREE;
+ if (dimen == 0)
+ {
+ arraytype = build_pointer_type (etype);
+ if (restricted)
+ arraytype = build_qualified_type (arraytype, TYPE_QUAL_RESTRICT);
+
+ GFC_TYPE_ARRAY_DATAPTR_TYPE (fat_type) = arraytype;
+ return fat_type;
+ }
+
/* We define data as an array with the correct size if possible.
Much better than doing pointer arithmetic. */
if (stride)
@@ -2835,8 +2846,11 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
gcc_assert (POINTER_TYPE_P (etype));
etype = TREE_TYPE (etype);
- gcc_assert (TREE_CODE (etype) == ARRAY_TYPE);
- etype = TREE_TYPE (etype);
+
+ /* If the type is not a scalar coarray. */
+ if (TREE_CODE (etype) == ARRAY_TYPE)
+ etype = TREE_TYPE (etype);
+
/* Can't handle variable sized elements yet. */
if (int_size_in_bytes (etype) <= 0)
return false;
diff --git a/gcc/testsuite/gfortran.dg/coarray_14.f90 b/gcc/testsuite/gfortran.dg/coarray_14.f90
index 3e3f046..49188d6 100644
--- a/gcc/testsuite/gfortran.dg/coarray_14.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_14.f90
@@ -49,7 +49,7 @@ type t
end type t
type(t), allocatable :: a[:]
allocate (t :: a) ! { dg-error "Coarray specification required in ALLOCATE statement" }
-allocate (t :: a[*]) ! { dg-error "allocatable scalar coarrays are not yet supported" }
+allocate (t :: a[*]) ! OK
end program myTest
! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_7.f90 b/gcc/testsuite/gfortran.dg/coarray_7.f90
index 29af0d1..abbd64d 100644
--- a/gcc/testsuite/gfortran.dg/coarray_7.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_7.f90
@@ -90,7 +90,7 @@ type(t), allocatable :: b(:)[:], C[:]
allocate(b(1)) ! { dg-error "Coarray specification" }
allocate(a[3]%a(5)) ! { dg-error "Coindexed allocatable" }
-allocate(c[*]) ! { dg-error "Sorry" }
+allocate(c[*]) ! OK
allocate(a%a(5)) ! OK
end subroutine alloc
@@ -151,9 +151,9 @@ subroutine allocateTest()
integer :: n, q
n = 1
q = 1
- allocate(a[q,*]) ! { dg-error "Sorry" }
- allocate(b[q,*]) ! { dg-error "Sorry" }
- allocate(c[q,*]) ! { dg-error "Sorry" }
+ allocate(a[q,*]) ! OK
+ allocate(b[q,*]) ! OK
+ allocate(c[q,*]) ! OK
end subroutine allocateTest
--- /dev/null 2011-07-11 07:57:37.363888622 +0200
+++ gcc/gcc/testsuite/gfortran.dg/coarray/scalar_alloc_1.f90 2011-07-11 09:31:34.000000000 +0200
@@ -0,0 +1,68 @@
+! { dg-do run }
+!
+implicit none
+integer, allocatable :: A[:], B[:,:]
+integer :: n1, n2, n3
+
+if (allocated (a)) call abort ()
+if (allocated (b)) call abort ()
+
+allocate(a[*])
+a = 5 + this_image ()
+if (a[this_image ()] /= 5 + this_image ()) call abort
+
+a[this_image ()] = 8 - 2*this_image ()
+if (a[this_image ()] /= 8 - 2*this_image ()) call abort
+
+if (lcobound(a, dim=1) /= 1 .or. ucobound(a,dim=1) /= num_images()) &
+ call abort ()
+deallocate(a)
+
+allocate(a[4:*])
+a[this_image ()] = 8 - 2*this_image ()
+
+if (lcobound(a, dim=1) /= 4 .or. ucobound(a,dim=1) /= 3 + num_images()) &
+ call abort ()
+
+n1 = -1
+n2 = 5
+n3 = 3
+allocate (B[n1:n2, n3:*])
+if (any (lcobound(b) /= [-1, 3]) .or. lcobound(B, dim=2) /= n3) &
+ call abort()
+call sub(A, B)
+
+if (allocated (a)) call abort ()
+if (.not.allocated (b)) call abort ()
+
+call two(.true.)
+call two(.false.)
+
+! automatically deallocate "B"
+contains
+ subroutine sub(x, y)
+ integer, allocatable :: x[:], y[:,:]
+
+ if (any (lcobound(y) /= [-1, 3]) .or. lcobound(y, dim=2) /= n3) &
+ call abort()
+ if (lcobound(x, dim=1) /= 4 .or. ucobound(x,dim=1) /= 3 + num_images()) &
+ call abort ()
+ if (x[this_image ()] /= 8 - 2*this_image ()) call abort
+ deallocate(x)
+ end subroutine sub
+
+ subroutine two(init)
+ logical, intent(in) :: init
+ integer, allocatable, SAVE :: a[:]
+
+ if (init) then
+ if (allocated(a)) call abort()
+ allocate(a[*])
+ a = 45
+ else
+ if (.not. allocated(a)) call abort()
+ if (a /= 45) call abort()
+ deallocate(a)
+ end if
+ end subroutine two
+end
--- /dev/null 2011-07-11 07:57:37.363888622 +0200
+++ gcc/gcc/testsuite/gfortran.dg/coarray/scalar_alloc_2.f90 2011-07-10 20:18:11.000000000 +0200
@@ -0,0 +1,60 @@
+! { dg-do run }
+!
+! Check whether registering allocatable coarrays works
+!
+type position
+ real :: x, y, z
+end type position
+
+integer, allocatable :: a[:]
+type(position), allocatable :: p[:]
+
+allocate(a[*])
+a = 7
+
+allocate(p[*])
+p%x = 11
+p%y = 13
+p%z = 15
+
+if (a /= 7) call abort()
+a = 88
+if (a /= 88) call abort()
+
+if (p%x /= 11) call abort()
+p%x = 17
+if (p%x /= 17) call abort()
+
+ block
+ integer, allocatable :: b[:]
+
+ allocate(b[*])
+ b = 8494
+
+ if (b /= 8494) call abort()
+ end block
+
+if (a /= 88) call abort()
+call test ()
+end
+
+subroutine test()
+ type velocity
+ real :: x, y, z
+ end type velocity
+
+ real, allocatable :: z[:]
+ type(velocity), allocatable :: v[:]
+
+ allocate(z[*])
+ z = sqrt(2.0)
+
+ allocate(v[*])
+ v%x = 21
+ v%y = 23
+ v%z = 25
+
+ if (z /= sqrt(2.0)) call abort()
+ if (v%x /= 21) call abort()
+
+end subroutine test
^ permalink raw reply [flat|nested] 10+ messages in thread
* *ping* - Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-11 7:54 ` Tobias Burnus
@ 2011-07-14 7:38 ` Tobias Burnus
2011-07-16 11:20 ` Tobias Burnus
2011-07-16 14:38 ` Mikael Morin
1 sibling, 1 reply; 10+ messages in thread
From: Tobias Burnus @ 2011-07-14 7:38 UTC (permalink / raw)
To: gcc patches, gfortran
*ping*
http://gcc.gnu.org/ml/fortran/2011-07/msg00106.html
On 07/11/2011 09:49 AM, Tobias Burnus wrote:
> On 07/10/2011 09:56 PM, Tobias Burnus wrote:
>> This patch implemented the trans*.c part of allocatable scalar
>> coarrays; contrary to noncoarray allocatable scalars, they have
>> cobounds and thus use an array descriptor.
>
> I found a test case (part of Reinhold Bader's fortran_tests), which
> gave an ICE: Allocatable scalar coarrays with SAVE.
>
> I have fixed that (trans-decl.c) and added a test.
>
>> The attached patch was build and regtested on x86-64-linux.
>> OK for the trunk?
>
> Tobias
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: *ping* - Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-14 7:38 ` *ping* - " Tobias Burnus
@ 2011-07-16 11:20 ` Tobias Burnus
0 siblings, 0 replies; 10+ messages in thread
From: Tobias Burnus @ 2011-07-16 11:20 UTC (permalink / raw)
To: gcc patches, gfortran
Sorry for pinging again, but the patch is large enough to block a bit my
progress ...
Other pending patches - which should be quickly reviewable::
- http://gcc.gnu.org/ml/fortran/2011-07/msg00170.html
- http://gcc.gnu.org/ml/fortran/2011-07/msg00142.html
Tobias
Tobias Burnus wrote:
> *ping*
> http://gcc.gnu.org/ml/fortran/2011-07/msg00106.html
>
> On 07/11/2011 09:49 AM, Tobias Burnus wrote:
>> On 07/10/2011 09:56 PM, Tobias Burnus wrote:
>>> This patch implemented the trans*.c part of allocatable scalar
>>> coarrays; contrary to noncoarray allocatable scalars, they have
>>> cobounds and thus use an array descriptor.
>>
>> I found a test case (part of Reinhold Bader's fortran_tests), which
>> gave an ICE: Allocatable scalar coarrays with SAVE.
>>
>> I have fixed that (trans-decl.c) and added a test.
>>
>>> The attached patch was build and regtested on x86-64-linux.
>>> OK for the trunk?
>>
>> Tobias
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-11 7:54 ` Tobias Burnus
2011-07-14 7:38 ` *ping* - " Tobias Burnus
@ 2011-07-16 14:38 ` Mikael Morin
2011-07-16 15:45 ` Tobias Burnus
1 sibling, 1 reply; 10+ messages in thread
From: Mikael Morin @ 2011-07-16 14:38 UTC (permalink / raw)
To: fortran; +Cc: Tobias Burnus, gcc patches
On Monday 11 July 2011 09:49:20 Tobias Burnus wrote:
> On 07/10/2011 09:56 PM, Tobias Burnus wrote:
> > This patch implemented the trans*.c part of allocatable scalar
> > coarrays; contrary to noncoarray allocatable scalars, they have
> > cobounds and thus use an array descriptor.
>
> I found a test case (part of Reinhold Bader's fortran_tests), which gave
> an ICE: Allocatable scalar coarrays with SAVE.
>
> I have fixed that (trans-decl.c) and added a test.
>
> > The attached patch was build and regtested on x86-64-linux.
> > OK for the trunk?
>
> Tobias
Hello,
let me understand one thing about coarray scalars: despite their name, they
are arrays, right?
Then when you do in gfc_conv_array_ref:
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
+ se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
[...]
return;
you are returning scalar[1] instead of scalar (== scalar[this_image()]) or
scalar[whatever_image_selector], aren't you?
Sorry for the delay; it seems that the more it goes, the more you are the only
one who can maintain coarray stuff. :-(
Mikael
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-16 14:38 ` Mikael Morin
@ 2011-07-16 15:45 ` Tobias Burnus
2011-07-16 17:05 ` Steve Kargl
2011-07-16 17:07 ` Mikael Morin
0 siblings, 2 replies; 10+ messages in thread
From: Tobias Burnus @ 2011-07-16 15:45 UTC (permalink / raw)
To: Mikael Morin; +Cc: fortran, gcc patches
Mikael Morin wrote:
> let me understand one thing about coarray scalars: despite their name, they
> are arrays, right?
Yes and no. In terms of the language, they are scalars - but they have a
codimension, e.g.
integer, save :: A[4:6, 7:*]
is a scalar variable on each image, but it has a coarank of 2 with
lcobound(A) == [4, 7] and ucobound(A, dim=1) == 7. (The value of
cobound(A, dim=2) depends on the number of images, it's >= 7 in this
example.)
In terms of gfortran, nonallocatable coarrays are normal scalars - with
a lang-specific node attached to them, which contains the cobounds, i.e.,
GFC_ARRAY_TYPE_P (type) = 1;
GFC_TYPE_ARRAY_CORANK (type) = as->corank;
with
GFC_TYPE_ARRAY_LBOUND (type, dim)
containing the trees for dim = (rank + 1) ... (rank + corank).
The same scheme is used for assumed-type coarrays:
subroutine sub(B, n)
integer :: B(:)[5:7, n:*]
Note that here that contrary to the dimension, the codimension is not
":" (i.e. assumed shape) but that it is assumed-size.
For allocatable (scalar) coarrays, one has:
integer, allocatable :: B[:, :] ! Note: The coshape is deferred
...
allocate (B[2:3, 5:*])
Again, one has the actual data and the cobounds. For that case, I have
decided to store the information in the array descriptor of rank == 0
and dim[0 ... corank-1] for the bounds. Thus, "desc->data" contains the
scalar but the variable itself is a descriptor (GFC_DESCRIPTOR_TYPE_P).
The corank is not stored in the descriptor, but as one knows the number
of codimensions (an explicit interface is required for allocatable
coarray dummies), one knows the corank.
> Then when you do in gfc_conv_array_ref:
>
> + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
> + se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
> [...]
> return;
>
> you are returning scalar[1] instead of scalar (== scalar[this_image()]) or
> scalar[whatever_image_selector], aren't you?
Well, the current implementation supports effectively only a single
image - for -fcoarray=single on purpose and for -fcoarray=lib because it
has not yet been implemented.
Later, one has to add some function call for "scalar[<image_numer>]"
while "scalar" itself is the local variable and can be handled as above.
The expression of "scalar" ends up having expr->ref->type == REF_ARRAY
with dimen_type == DIMEN_THIS_IMAGE. That way one can distinguish a
reference to the local coarray and to a remote coarray (coindexed
variable); note that "coarray[this_image()]" also counts as
remote/coindexed.
> Sorry for the delay; it seems that the more it goes, the more you are the only
> one who can maintain coarray stuff. :-(
Well, Daniel Carrera develops into an trans*.c, allocate,
libgfortran/caf/ expert :-)
Tobias
PS: I should document somewhere how coarrays are implemented internally.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-16 15:45 ` Tobias Burnus
@ 2011-07-16 17:05 ` Steve Kargl
2011-07-16 17:07 ` Mikael Morin
1 sibling, 0 replies; 10+ messages in thread
From: Steve Kargl @ 2011-07-16 17:05 UTC (permalink / raw)
To: Tobias Burnus; +Cc: Mikael Morin, fortran, gcc patches
On Sat, Jul 16, 2011 at 05:25:36PM +0200, Tobias Burnus wrote:
>
> PS: I should document somewhere how coarrays are implemented internally.
gcc/gcc4x/gcc/fortran/gfc-internals.texi
:-)
--
Steve
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-16 15:45 ` Tobias Burnus
2011-07-16 17:05 ` Steve Kargl
@ 2011-07-16 17:07 ` Mikael Morin
2011-07-16 19:59 ` Daniel Carrera
2011-07-16 22:57 ` Tobias Burnus
1 sibling, 2 replies; 10+ messages in thread
From: Mikael Morin @ 2011-07-16 17:07 UTC (permalink / raw)
To: fortran; +Cc: Tobias Burnus, gcc patches
On Saturday 16 July 2011 17:25:36 Tobias Burnus wrote:
> Mikael Morin wrote:
> > let me understand one thing about coarray scalars: despite their name,
> > they are arrays, right?
>
> Yes and no. In terms of the language, they are scalars - but they have a
> codimension, e.g.
> integer, save :: A[4:6, 7:*]
> is a scalar variable on each image, but it has a coarank of 2 with
> lcobound(A) == [4, 7] and ucobound(A, dim=1) == 7.
ucobound(A, dim=1) == 6 ? Otherwise I'm even more confused.
> > Then when you do in gfc_conv_array_ref:
> >
> > + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
> > + se->expr = build_fold_indirect_ref (gfc_conv_array_data
> > (se->expr)); [...]
> >
> > return;
> >
> > you are returning scalar[1] instead of scalar (== scalar[this_image()])
> > or scalar[whatever_image_selector], aren't you?
>
> Well, the current implementation supports effectively only a single
> image - for -fcoarray=single on purpose and for -fcoarray=lib because it
> has not yet been implemented.
>
> Later, one has to add some function call for "scalar[<image_numer>]"
> while "scalar" itself is the local variable and can be handled as above.
Ah, OK; that's where I was misunderstanding coarrays. I was thinking that a
(possibly out of date) copy of remote images was available locally, like a
normal array; and with any network exchanges happening during the SYNC* calls
only.
In fact network traffic happens anywhere there are square brackets, and SYNC*
are mere iddle waits, right?
> The expression of "scalar" ends up having expr->ref->type == REF_ARRAY
> with dimen_type == DIMEN_THIS_IMAGE. That way one can distinguish a
> reference to the local coarray and to a remote coarray (coindexed
> variable); note that "coarray[this_image()]" also counts as
> remote/coindexed.
While it seems to work well, we would probably have gained some clarity by
using a separate struct for coarray references.
For example with the current scheme, array[1,2] has type ARRAY_FULL, but some
dimen_type are of type DIMEN_ELEMENT. Odd.
> > Sorry for the delay; it seems that the more it goes, the more you are the
> > only one who can maintain coarray stuff. :-(
>
> Well, Daniel Carrera develops into an trans*.c, allocate,
> libgfortran/caf/ expert :-)
>
Thanks for all the clarifications. Patch is OK (I guess).
Mikael
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-16 17:07 ` Mikael Morin
@ 2011-07-16 19:59 ` Daniel Carrera
2011-07-16 22:57 ` Tobias Burnus
1 sibling, 0 replies; 10+ messages in thread
From: Daniel Carrera @ 2011-07-16 19:59 UTC (permalink / raw)
To: Mikael Morin; +Cc: fortran, Tobias Burnus, gcc patches
On 07/16/2011 06:43 PM, Mikael Morin wrote:
>> Well, the current implementation supports effectively only a single
>> image - for -fcoarray=single on purpose and for -fcoarray=lib because it
>> has not yet been implemented.
>>
>> Later, one has to add some function call for "scalar[<image_numer>]"
>> while "scalar" itself is the local variable and can be handled as above.
> Ah, OK; that's where I was misunderstanding coarrays. I was thinking that a
> (possibly out of date) copy of remote images was available locally, like a
> normal array; and with any network exchanges happening during the SYNC* calls
> only.
> In fact network traffic happens anywhere there are square brackets, and SYNC*
> are mere iddle waits, right?
I am no expert, but I'll try to answer: Yes.
Yes, network traffic happens whenever there are square brackets and no
copies are stored locally. However, you have no guarantee of how far
ahead other images are. For example:
real :: foo[:]
foo = this_image()
if (this_image() == 1) then
foo = foo + foo[2]
end if
if (this_image() == 2) then
foo = foo + foo[1]
end if
This program could do all sorts of crazy things. As you said, the SYNC
is a idle wait, just to make processes wait for each other. The
following program is predictable:
real :: foo[:]
foo = this_image()
sync all
if (this_image() == 1) then
foo = foo + foo[2]
end if
sync all
if (this_image() == 2) then
foo = foo + foo[1]
end if
Cheers,
Daniel.
--
I'm not overweight, I'm undertall.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch, Fortran] Support allocatable *scalar* coarrays
2011-07-16 17:07 ` Mikael Morin
2011-07-16 19:59 ` Daniel Carrera
@ 2011-07-16 22:57 ` Tobias Burnus
1 sibling, 0 replies; 10+ messages in thread
From: Tobias Burnus @ 2011-07-16 22:57 UTC (permalink / raw)
To: Mikael Morin; +Cc: fortran, gcc patches
Mikael Morin wrote:
> On Saturday 16 July 2011 17:25:36 Tobias Burnus wrote:
>> integer, save :: A[4:6, 7:*]
>> is a scalar variable on each image, but it has a coarank of 2 with
>> lcobound(A) == [4, 7] and ucobound(A, dim=1) == 7.
> ucobound(A, dim=1) == 6 ? Otherwise I'm even more confused.
Sorry for the typo. It's indeed 6.
> Ah, OK; that's where I was misunderstanding coarrays. I was thinking that a
> (possibly out of date) copy of remote images was available locally, like a
> normal array; and with any network exchanges happening during the SYNC* calls
> only. In fact network traffic happens anywhere there are square brackets, and SYNC*
> are mere iddle waits, right?
In terms of the Fortran standard: Yes. In terms of the implementation:
It depends. For the front end: It simply requests to receive (or send)
remote data when it sees a "[...]" - for pushing data to an remote
image, it might even be asynchrnous.
However, the current plan for libcaf_mpi is that one has two-sided
communication; the image which wants to have the content of a remote
image sends a request - and waits for the answer while continuing to
process incoming requests. Thus, if the image is unlucky, it has to wait
until the other image hits a SYNC and can then answer requests. If it is
lucky, the other image also has some remove access and can directly
process the request.
Via a helper process, the answer could be provided faster - or via
one-sided communication - or in case of a shared memory implementation.
> While it seems to work well, we would probably have gained some clarity by
> using a separate struct for coarray references.
> For example with the current scheme, array[1,2] has type ARRAY_FULL, but some
> dimen_type are of type DIMEN_ELEMENT. Odd.
Presumably. The problem is that codimensions act on one hand like normal
dimensions but on the other hand they are different. When declaring
them, "rank + corank <= 15", adding them as extra dimension is also
logical etc. On the other hand, when referencing a local coarray, one
has no brackets and if there is a bracket, one can only give an element
(single coarray) and not a range or vector.
> Thanks for all the clarifications. Patch is OK (I guess).
Thanks for the review!
Tobias
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-07-16 17:21 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-10 21:16 [Patch, Fortran] Support allocatable *scalar* coarrays Tobias Burnus
2011-07-11 7:54 ` Tobias Burnus
2011-07-14 7:38 ` *ping* - " Tobias Burnus
2011-07-16 11:20 ` Tobias Burnus
2011-07-16 14:38 ` Mikael Morin
2011-07-16 15:45 ` Tobias Burnus
2011-07-16 17:05 ` Steve Kargl
2011-07-16 17:07 ` Mikael Morin
2011-07-16 19:59 ` Daniel Carrera
2011-07-16 22:57 ` Tobias Burnus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).