* [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
@ 2012-07-20 10:20 Tobias Burnus
2012-07-21 10:41 ` Mikael Morin
0 siblings, 1 reply; 11+ messages in thread
From: Tobias Burnus @ 2012-07-20 10:20 UTC (permalink / raw)
To: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 904 bytes --]
Dear all,
this patch is a cleanup follow up to the assumed-rank patch. Changes:
* Fix pattern matching for the dump. for some reason, the DTYPE differes
between i686 and x86-64.
* There was a proper check missing that assumed-rank arrays may not have
a codimension. (There are now checks in array.c, decl.c and -
preexisting - resolve.c, all are triggered by the test case _11.)
* I re-added my lbound/ubound patch. It still only works with dim=.
For lbound/ubound without dim= and for shape, one has to modify the
scalarizer a bit. See discussion at
http://gcc.gnu.org/ml/fortran/2012-07/msg00032.html
Mikael: I wouldn't mind if you could have a look at the scalarizer - you
seem to have an idea how one can implement it with minimal effort/code
cluttering.
Build and regtested on x86-64-linux.
OK for the trunk?
Tobias
PS: Sorry for missing the regression failure before the committal.
[-- Attachment #2: assumed-rank-bounds.diff --]
[-- Type: text/x-patch, Size: 17166 bytes --]
2012-07-20 Tobias Burnus <burnus@net-b.de>
PR fortran/48820
* trans-intrinsic.c (gfc_conv_intrinsic_bound): Support
lbound/ubound with dim= for assumed-rank arrays.
* array.c (gfc_set_array_spec): Reject coarrays with
assumed shape.
* decl.c (merge_array_spec): Ditto. Return gfc_try.
(match_attr_spec, match_attr_spec): Update call.
2012-07-20 Tobias Burnus <burnus@net-b.de>
PR fortran/48820
* gfortran.dg/assumed_rank_3.f90: New.
* gfortran.dg/assumed_rank_11.f90: New.
* gfortran.dg/assumed_rank_1.f90: Update dg-error.
* gfortran.dg/assumed_rank_2.f90: Update dg-error.
* gfortran.dg/assumed_rank_7.f90: Update dg-error.
* gfortran.dg/assumed_rank_12.f90: Update dg-error.
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index acae59f..1b700b8 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -750,6 +750,14 @@ gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
return SUCCESS;
}
+ if ((sym->as->type == AS_ASSUMED_RANK && as->corank)
+ || (as->type == AS_ASSUMED_RANK && sym->as->corank))
+ {
+ gfc_error ("The assumed-rank array '%s' at %L shall not have a "
+ "codimension", sym->name, error_loc);
+ return FAILURE;
+ }
+
if (as->corank)
{
/* The "sym" has no corank (checked via gfc_add_codimension). Thus
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 66e2ca8..c836b25 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -589,13 +589,17 @@ cleanup:
/* Auxiliary function to merge DIMENSION and CODIMENSION array specs. */
-static void
+static gfc_try
merge_array_spec (gfc_array_spec *from, gfc_array_spec *to, bool copy)
{
int i;
- gcc_assert (from->rank != -1 || to->corank == 0);
- gcc_assert (to->rank != -1 || from->corank == 0);
+ if ((from->type == AS_ASSUMED_RANK && to->corank)
+ || (to->type == AS_ASSUMED_RANK && from->corank))
+ {
+ gfc_error ("The assumed-rank array at %C shall not have a codimension");
+ return FAILURE;
+ }
if (to->rank == 0 && from->rank > 0)
{
@@ -642,6 +646,8 @@ merge_array_spec (gfc_array_spec *from, gfc_array_spec *to, bool copy)
}
}
}
+
+ return SUCCESS;
}
@@ -1813,8 +1805,12 @@ variable_decl (int elem)
if (m == MATCH_NO)
as = gfc_copy_array_spec (current_as);
- else if (current_as)
- merge_array_spec (current_as, as, true);
+ else if (current_as
+ && merge_array_spec (current_as, as, true) == FAILURE)
+ {
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
if (gfc_option.flag_cray_pointer)
cp_as = gfc_copy_array_spec (as);
@@ -3526,7 +3522,8 @@ match_attr_spec (void)
current_as = as;
else if (m == MATCH_YES)
{
- merge_array_spec (as, current_as, false);
+ if (merge_array_spec (as, current_as, false) == FAILURE)
+ m = MATCH_ERROR;
free (as);
}
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index be94219..7bcfda9 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -1367,6 +1367,7 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
gfc_se argse;
gfc_ss *ss;
gfc_array_spec * as;
+ bool assumed_rank_lb_one;
arg = expr->value.function.actual;
arg2 = arg->next;
@@ -1408,27 +1409,36 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
desc = argse.expr;
+ as = gfc_get_full_arrayspec_from_expr (arg->expr);
+
if (INTEGER_CST_P (bound))
{
int hi, low;
hi = TREE_INT_CST_HIGH (bound);
low = TREE_INT_CST_LOW (bound);
- if (hi || low < 0 || low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
+ if (hi || low < 0
+ || ((!as || as->type != AS_ASSUMED_RANK)
+ && low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
+ || low > GFC_MAX_DIMENSIONS)
gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
"dimension index", upper ? "UBOUND" : "LBOUND",
&expr->where);
}
- else
+
+ if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
{
if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
{
bound = gfc_evaluate_now (bound, &se->pre);
cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
bound, build_int_cst (TREE_TYPE (bound), 0));
- tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
+ if (as && as->type == AS_ASSUMED_RANK)
+ tmp = get_rank_from_desc (desc);
+ else
+ tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
- bound, tmp);
+ bound, fold_convert(TREE_TYPE (bound), tmp));
cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
boolean_type_node, cond, tmp);
gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
@@ -1436,11 +1446,19 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
}
}
+ /* Take care of the lbound shift for assumed-rank arrays, which are
+ nonallocatable and nonpointers. Those has a lbound of 1. */
+ assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
+ && ((arg->expr->ts.type != BT_CLASS
+ && !arg->expr->symtree->n.sym->attr.allocatable
+ && !arg->expr->symtree->n.sym->attr.pointer)
+ || (arg->expr->ts.type == BT_CLASS
+ && !CLASS_DATA (arg->expr)->attr.allocatable
+ && !CLASS_DATA (arg->expr)->attr.class_pointer));
+
ubound = gfc_conv_descriptor_ubound_get (desc, bound);
lbound = gfc_conv_descriptor_lbound_get (desc, bound);
- as = gfc_get_full_arrayspec_from_expr (arg->expr);
-
/* 13.14.53: Result value for LBOUND
Case (i): For an array section or for an array expression other than a
@@ -1462,7 +1480,9 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
not have size zero and has value zero if dimension DIM has
size zero. */
- if (as)
+ if (!upper && assumed_rank_lb_one)
+ se->expr = gfc_index_one_node;
+ else if (as)
{
tree stride = gfc_conv_descriptor_stride_get (desc, bound);
@@ -1488,9 +1508,19 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
boolean_type_node, cond, cond5);
+ if (assumed_rank_lb_one)
+ {
+ tmp = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type, ubound, lbound);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR,
+ gfc_array_index_type, tmp, gfc_index_one_node);
+ }
+ else
+ tmp = ubound;
+
se->expr = fold_build3_loc (input_location, COND_EXPR,
gfc_array_index_type, cond,
- ubound, gfc_index_zero_node);
+ tmp, gfc_index_zero_node);
}
else
{
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_1.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_1.f90
index d68f1f9..44e278c 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_1.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_1.f90
@@ -5,8 +5,6 @@
!
! Assumed-rank tests
!
-! FIXME: The ubound/lbound checks have to be re-enabled when
-! after they are supported
implicit none
@@ -106,14 +104,14 @@ contains
if (size(a) /= product (high - low +1)) call abort()
if (rnk > 0) then
-! if (1 /= lbound(a,1)) call abort()
-! if (high(1)-low(1)+1 /= ubound(a,1)) call abort()
+ if (1 /= lbound(a,1)) call abort()
+ if (high(1)-low(1)+1 /= ubound(a,1)) call abort()
if (size (a,1) /= high(1)-low(1)+1) call abort()
end if
do i = 1, rnk
-! if (1 /= lbound(a,i)) call abort()
-! if (high(i)-low(i)+1 /= ubound(a,i)) call abort()
+ if (1 /= lbound(a,i)) call abort()
+ if (high(i)-low(i)+1 /= ubound(a,i)) call abort()
if (size (a,i) /= high(i)-low(i)+1) call abort()
end do
call check_value (a, rnk, val)
@@ -131,14 +129,14 @@ contains
if (size(a) /= product (high - low +1)) call abort()
if (rnk > 0) then
-! if (low(1) /= lbound(a,1)) call abort()
-! if (high(1) /= ubound(a,1)) call abort()
+ if (low(1) /= lbound(a,1)) call abort()
+ if (high(1) /= ubound(a,1)) call abort()
if (size (a,1) /= high(1)-low(1)+1) call abort()
end if
do i = 1, rnk
-! if (low(i) /= lbound(a,i)) call abort()
-! if (high(i) /= ubound(a,i)) call abort()
+ if (low(i) /= lbound(a,i)) call abort()
+ if (high(i) /= ubound(a,i)) call abort()
if (size (a,i) /= high(i)-low(i)+1) call abort()
end do
call check_value (a, rnk, val)
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_12.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_12.f90
index a2abcba..f947f49 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_12.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_12.f90
@@ -16,6 +16,6 @@ function f() result(res)
end function f
end
-! { dg-final { scan-tree-dump " = f \\(\\);.*desc.0.dtype = 600;.*desc.0.data = .void .. D.*;.*sub \\(&desc.0\\);.*D.*= .integer.kind=4. .. desc.0.data;" "original" } }
+! { dg-final { scan-tree-dump " = f \\(\\);.*desc.0.dtype = .*;.*desc.0.data = .void .. D.*;.*sub \\(&desc.0\\);.*D.*= .integer.kind=4. .. desc.0.data;" "original" } }
! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_2.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_2.f90
index 981e5cc2..344278e 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_2.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_2.f90
@@ -6,8 +6,6 @@
! Assumed-rank tests - same as assumed_rank_1.f90,
! but with bounds checks and w/o call to C function
!
-! FIXME: The ubound/lbound checks have to be re-enabled when
-! after they are supported
implicit none
@@ -73,14 +71,14 @@ contains
if (size(a) /= product (high - low +1)) call abort()
if (rnk > 0) then
-! if (low(1) /= lbound(a,1)) call abort()
-! if (high(1) /= ubound(a,1)) call abort()
+ if (low(1) /= lbound(a,1)) call abort()
+ if (high(1) /= ubound(a,1)) call abort()
if (size (a,1) /= high(1)-low(1)+1) call abort()
end if
do i = 1, rnk
-! if (low(i) /= lbound(a,i)) call abort()
-! if (high(i) /= ubound(a,i)) call abort()
+ if (low(i) /= lbound(a,i)) call abort()
+ if (high(i) /= ubound(a,i)) call abort()
if (size (a,i) /= high(i)-low(i)+1) call abort()
end do
call foo2(a, rnk, low, high, val)
@@ -98,14 +96,14 @@ contains
if (size(a) /= product (high - low +1)) call abort()
if (rnk > 0) then
-! if (1 /= lbound(a,1)) call abort()
-! if (high(1)-low(1)+1 /= ubound(a,1)) call abort()
+ if (1 /= lbound(a,1)) call abort()
+ if (high(1)-low(1)+1 /= ubound(a,1)) call abort()
if (size (a,1) /= high(1)-low(1)+1) call abort()
end if
do i = 1, rnk
-! if (1 /= lbound(a,i)) call abort()
-! if (high(i)-low(i)+1 /= ubound(a,i)) call abort()
+ if (1 /= lbound(a,i)) call abort()
+ if (high(i)-low(i)+1 /= ubound(a,i)) call abort()
if (size (a,i) /= high(i)-low(i)+1) call abort()
end do
end subroutine foo2
@@ -122,14 +120,14 @@ contains
if (size(a) /= product (high - low +1)) call abort()
if (rnk > 0) then
-! if (low(1) /= lbound(a,1)) call abort()
-! if (high(1) /= ubound(a,1)) call abort()
+ if (low(1) /= lbound(a,1)) call abort()
+ if (high(1) /= ubound(a,1)) call abort()
if (size (a,1) /= high(1)-low(1)+1) call abort()
end if
do i = 1, rnk
-! if (low(i) /= lbound(a,i)) call abort()
-! if (high(i) /= ubound(a,i)) call abort()
+ if (low(i) /= lbound(a,i)) call abort()
+ if (high(i) /= ubound(a,i)) call abort()
if (size (a,i) /= high(i)-low(i)+1) call abort()
end do
call foo(a, rnk, low, high, val)
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_6.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_6.f90
index e5071bd..86da3f8 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_6.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_6.f90
@@ -30,8 +30,8 @@ contains
end subroutine
end subroutine
-subroutine foo4(x) ! { dg-error "may not have the VALUE or CODIMENSION attribute" }
- integer, codimension[*] :: x(..)
+subroutine foo4(x)
+ integer, codimension[*] :: x(..) ! { dg-error "The assumed-rank array at .1. shall not have a codimension" }
end subroutine
subroutine foo5(y) ! { dg-error "may not have the VALUE or CODIMENSION attribute" }
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_7.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_7.f90
index 96d4d8f..f9ff3b9 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_7.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_7.f90
@@ -4,8 +4,6 @@
!
! Handle type/class for assumed-rank arrays
!
-! FIXME: The ubound/lbound checks have to be re-enabled when
-! after they are supported.
! FIXME: Passing a CLASS to a CLASS has to be re-enabled.
implicit none
type t
@@ -29,38 +27,38 @@ if (i /= 12) call abort()
contains
subroutine bar(x)
type(t) :: x(..)
-! if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
+ if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
if (size(x) /= 6) call abort()
if (size(x,1) /= 2 .or. size(x,2) /= 3) call abort()
-! if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
+ if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
i = i + 1
call foo(x)
call bar2(x)
end subroutine
subroutine bar2(x)
type(t) :: x(..)
-! if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
+ if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
if (size(x) /= 6) call abort()
if (size(x,1) /= 2 .or. size(x,2) /= 3) call abort()
-! if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
+ if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
i = i + 1
end subroutine
subroutine foo(x)
class(t) :: x(..)
-! if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
+ if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
if (size(x) /= 6) call abort()
if (size(x,1) /= 2 .or. size(x,2) /= 3) call abort()
-! if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
+ if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
i = i + 1
call foo2(x)
! call bar2(x) ! Passing a CLASS to a TYPE does not yet work
end subroutine
subroutine foo2(x)
class(t) :: x(..)
-! if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
+ if (lbound(x,1) /= 1 .or. lbound(x,2) /= 1) call abort()
if (size(x) /= 6) call abort()
if (size(x,1) /= 2 .or. size(x,2) /= 3) call abort()
-! if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
+ if (ubound(x,1) /= 2 .or. ubound(x,2) /= 3) call abort()
i = i + 1
end subroutine
end
--- /dev/null 2012-07-18 07:03:52.759757921 +0200
+++ gcc/gcc/testsuite/gfortran.dg/assumed_rank_3.f90 2012-06-24 15:17:43.000000000 +0200
@@ -0,0 +1,19 @@
+! { dg-do run }
+! { dg-options "-fcheck=bounds" }
+! { dg-shouldfail "Array reference out of bounds" }
+!
+! PR fortran/48820
+!
+! Do assumed-rank bound checking
+
+implicit none
+integer :: a(4,4)
+call bar(a)
+contains
+ subroutine bar(x)
+ integer :: x(..)
+ print *, ubound(x,dim=3) ! << wrong dim
+ end subroutine
+end
+
+! { dg-output "Fortran runtime error: Array reference out of bounds" }
--- /dev/null 2012-07-18 07:03:52.759757921 +0200
+++ gcc/gcc/testsuite/gfortran.dg/assumed_rank_11.f90 2012-07-20 10:35:39.000000000 +0200
@@ -0,0 +1,52 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+! PR fortran/48820
+!
+! Assumed-rank tests
+subroutine foo(X)
+ integer :: x(..)
+ codimension :: x[*] ! { dg-error "The assumed-rank array 'x' at .1. shall not have a codimension" }
+end
+
+subroutine foo2(X)
+ integer, dimension(..) :: x[*] ! { dg-error "The assumed-rank array at .1. shall not have a codimension" }
+end
+
+subroutine foo3(X)
+ integer, codimension[*] :: x(..) ! { dg-error "The assumed-rank array at .1. shall not have a codimension" }
+end
+
+subroutine foo4(X)
+ integer, codimension[*], dimension(..) :: x ! { dg-error "The assumed-rank array at .1. shall not have a codimension" }
+end
+
+subroutine bar(X)
+ integer :: x[*]
+ dimension :: x(..) ! { dg-error "The assumed-rank array 'x' at .1. shall not have a codimension" }
+end
+
+subroutine foobar(X)
+ integer :: x
+ codimension :: x[*]
+ dimension :: x(..) ! { dg-error "The assumed-rank array 'x' at .1. shall not have a codimension" }
+end
+
+subroutine barfoo(X)
+ integer :: x
+ dimension :: x(..)
+ codimension :: x[*] ! { dg-error "The assumed-rank array 'x' at .1. shall not have a codimension" }
+end
+
+subroutine orig(X) ! { dg-error "may not have the VALUE or CODIMENSION attribute" }
+ integer :: x(..)[*]
+end
+
+subroutine val1(X)
+ integer, value :: x(..) ! { dg-error "VALUE attribute conflicts with DIMENSION attribute" }
+end
+
+subroutine val2(X)
+ integer, value :: x
+ dimension :: x(..) ! { dg-error "VALUE attribute conflicts with DIMENSION attribute" }
+end
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-20 10:20 [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs Tobias Burnus
@ 2012-07-21 10:41 ` Mikael Morin
2012-07-21 11:08 ` Tobias Burnus
0 siblings, 1 reply; 11+ messages in thread
From: Mikael Morin @ 2012-07-21 10:41 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc patches, gfortran
On 20/07/2012 12:19, Tobias Burnus wrote:
> Mikael: I wouldn't mind if you could have a look at the scalarizer - you
> seem to have an idea how one can implement it with minimal effort/code
> cluttering.
This is exaggerated. I just said that the scalarizer can't generate a
variable number of loops.
I can have a look next week. Could you post what is left from your
initial {l,u}bound patch? It has been raining assumed rank patches and
I'm lost now.
>
>
> Build and regtested on x86-64-linux.
> OK for the trunk?
>
OK.
Mikael
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-21 10:41 ` Mikael Morin
@ 2012-07-21 11:08 ` Tobias Burnus
2012-07-26 14:55 ` Mikael Morin
0 siblings, 1 reply; 11+ messages in thread
From: Tobias Burnus @ 2012-07-21 11:08 UTC (permalink / raw)
To: Mikael Morin; +Cc: gcc patches, gfortran
Mikael Morin wrote:
> On 20/07/2012 12:19, Tobias Burnus wrote:
>> Build and regtested on x86-64-linux.
>> OK for the trunk?
>>
> OK.
Thanks! Committed as Rev. 189743.
>> Mikael: I wouldn't mind if you could have a look at the scalarizer - you
>> seem to have an idea how one can implement it with minimal effort/code
>> cluttering.
> This is exaggerated. I just said that the scalarizer can't generate a variable number of loops. I can have a look next week. Could you post what is left from your initial {l,u}bound patch? It has been raining assumed rank patches and I'm lost now.
Well, the good news is that the just approved/committed patch contains
everything which I had before. It turned out that I don't need the
scalarizer change for the current implementation.
Thus, lbound(x, dim=i) works now; as do ubound(x, dim=i) and
size(x)/size(x,dim=i).
Only failing are:
lbound(x) / ubound(x) / shape(x)
Thanks for offering to take a look!
In terms of pending patches, I currently only have one: The just posted
C_PTRDIFF_T patch.
Tobias
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-21 11:08 ` Tobias Burnus
@ 2012-07-26 14:55 ` Mikael Morin
2012-07-26 15:14 ` Mikael Morin
0 siblings, 1 reply; 11+ messages in thread
From: Mikael Morin @ 2012-07-26 14:55 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 171 bytes --]
On 21/07/2012 13:08, Tobias Burnus wrote:
> Only failing are:
> lbound(x) / ubound(x) / shape(x)
>
Here is a draft for those.
Lightly tested with print *, ...
Mikael
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: assumed_rank.diff --]
[-- Type: text/x-patch; name="assumed_rank.diff", Size: 7098 bytes --]
Index: trans-array.c
===================================================================
--- trans-array.c (révision 189883)
+++ trans-array.c (copie de travail)
@@ -249,6 +249,20 @@ gfc_conv_descriptor_dtype (tree desc)
tree
+gfc_conv_descriptor_rank (tree desc)
+{
+ tree tmp;
+ tree dtype;
+
+ dtype = gfc_conv_descriptor_dtype (desc);
+ tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
+ tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
+ dtype, tmp);
+ return fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
+}
+
+
+tree
gfc_get_descriptor_dimension (tree desc)
{
tree type, field;
@@ -3794,6 +3808,40 @@ done:
/* Fall through to supply start and stride. */
case GFC_ISYM_LBOUND:
case GFC_ISYM_UBOUND:
+ {
+ gfc_expr *arg;
+
+ /* This is the variant without DIM=... */
+ gcc_assert (expr->value.function.actual->next->expr == NULL);
+
+ arg = expr->value.function.actual->expr;
+ if (arg->rank == -1)
+ {
+ gfc_se se;
+ tree rank, tmp;
+
+ /* The rank (hence the return value's shape) is unknown,
+ we have to retrieve it. */
+ gfc_init_se (&se, NULL);
+ se.descriptor_only = 1;
+ gfc_conv_expr (&se, arg);
+ /* This is a bare variable, so there is no preliminary
+ or cleanup code. */
+ gcc_assert (se.pre.head == NULL_TREE
+ && se.post.head == NULL_TREE);
+ rank = gfc_conv_descriptor_rank (se.expr);
+ tmp = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type,
+ fold_convert (gfc_array_index_type,
+ rank),
+ gfc_index_one_node);
+ info->end[0] = gfc_evaluate_now (tmp, &loop->pre);
+ info->start[0] = gfc_index_zero_node;
+ info->stride[0] = gfc_index_one_node;
+ continue;
+ }
+ /* Otherwise fall through GFC_SS_FUNCTION. */
+ }
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_THIS_IMAGE:
@@ -4430,22 +4478,11 @@ set_loop_bounds (gfc_loopinfo *loop)
continue;
}
- /* TODO: Pick the best bound if we have a choice between a
- function and something else. */
- if (ss_type == GFC_SS_FUNCTION)
- {
- loopspec[n] = ss;
- continue;
- }
-
/* Avoid using an allocatable lhs in an assignment, since
there might be a reallocation coming. */
if (loopspec[n] && ss->is_alloc_lhs)
continue;
- if (ss_type != GFC_SS_SECTION)
- continue;
-
if (!loopspec[n])
loopspec[n] = ss;
/* Criteria for choosing a loop specifier (most important first):
@@ -4520,6 +4557,20 @@ set_loop_bounds (gfc_loopinfo *loop)
gcc_assert (loop->to[n] == NULL_TREE);
break;
+ case GFC_SS_INTRINSIC:
+ {
+ gfc_expr *expr = loopspec[n]->info->expr;
+
+ /* The {l,u}bound of an assumed rank. */
+ gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
+ || expr->value.function.isym->id == GFC_ISYM_UBOUND)
+ && expr->value.function.actual->next->expr == NULL
+ && expr->value.function.actual->expr->rank == -1);
+
+ loop->to[n] = info->end[dim];
+ break;
+ }
+
default:
gcc_unreachable ();
}
Index: trans-array.h
===================================================================
--- trans-array.h (révision 189881)
+++ trans-array.h (copie de travail)
@@ -154,6 +154,7 @@ tree gfc_conv_descriptor_data_get (tree);
tree gfc_conv_descriptor_data_addr (tree);
tree gfc_conv_descriptor_offset_get (tree);
tree gfc_conv_descriptor_dtype (tree);
+tree gfc_conv_descriptor_rank (tree);
tree gfc_get_descriptor_dimension (tree);
tree gfc_conv_descriptor_stride_get (tree, tree);
tree gfc_conv_descriptor_lbound_get (tree, tree);
Index: iresolve.c
===================================================================
--- iresolve.c (révision 189881)
+++ iresolve.c (copie de travail)
@@ -134,9 +134,12 @@ resolve_bound (gfc_expr *f, gfc_expr *array, gfc_e
if (dim == NULL)
{
f->rank = 1;
- f->shape = gfc_get_shape (1);
- mpz_init_set_ui (f->shape[0], coarray ? gfc_get_corank (array)
- : array->rank);
+ if (array->rank != -1)
+ {
+ f->shape = gfc_get_shape (1);
+ mpz_init_set_ui (f->shape[0], coarray ? gfc_get_corank (array)
+ : array->rank);
+ }
}
f->value.function.name = xstrdup (name);
@@ -2225,8 +2228,12 @@ gfc_resolve_shape (gfc_expr *f, gfc_expr *array, g
f->ts.kind = gfc_default_integer_kind;
f->rank = 1;
- f->shape = gfc_get_shape (1);
- mpz_init_set_ui (f->shape[0], array->rank);
+ if (array->rank != -1)
+ {
+ f->shape = gfc_get_shape (1);
+ mpz_init_set_ui (f->shape[0], array->rank);
+ }
+
f->value.function.name = gfc_get_string (PREFIX ("shape_%d"), f->ts.kind);
}
Index: trans-intrinsic.c
===================================================================
--- trans-intrinsic.c (révision 189881)
+++ trans-intrinsic.c (copie de travail)
@@ -1315,20 +1315,6 @@ trans_num_images (gfc_se * se)
}
-static tree
-get_rank_from_desc (tree desc)
-{
- tree tmp;
- tree dtype;
-
- dtype = gfc_conv_descriptor_dtype (desc);
- tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
- tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
- dtype, tmp);
- return fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
-}
-
-
static void
gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
{
@@ -1345,7 +1331,7 @@ gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *exp
gfc_add_block_to_block (&se->pre, &argse.pre);
gfc_add_block_to_block (&se->post, &argse.post);
- se->expr = get_rank_from_desc (argse.expr);
+ se->expr = gfc_conv_descriptor_rank (argse.expr);
}
@@ -1434,7 +1420,7 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr *
cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
bound, build_int_cst (TREE_TYPE (bound), 0));
if (as && as->type == AS_ASSUMED_RANK)
- tmp = get_rank_from_desc (desc);
+ tmp = gfc_conv_descriptor_rank (desc);
else
tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
@@ -5895,7 +5881,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
gfc_conv_expr_lhs (&arg1se, arg1->expr);
if (arg1->expr->rank == -1)
{
- tmp = get_rank_from_desc (arg1se.expr);
+ tmp = gfc_conv_descriptor_rank (arg1se.expr);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
TREE_TYPE (tmp), tmp, gfc_index_one_node);
}
Index: simplify.c
===================================================================
--- simplify.c (révision 189881)
+++ simplify.c (copie de travail)
@@ -5470,6 +5470,9 @@ gfc_simplify_shape (gfc_expr *source, gfc_expr *ki
gfc_try t;
int k = get_kind (BT_INTEGER, kind, "SHAPE", gfc_default_integer_kind);
+ if (source->rank == -1)
+ return NULL;
+
result = gfc_get_array_expr (BT_INTEGER, k, &source->where);
if (source->rank == 0)
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-26 14:55 ` Mikael Morin
@ 2012-07-26 15:14 ` Mikael Morin
2012-07-26 15:32 ` Tobias Burnus
0 siblings, 1 reply; 11+ messages in thread
From: Mikael Morin @ 2012-07-26 15:14 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 412 bytes --]
On 26/07/2012 16:53, Mikael Morin wrote:
> On 21/07/2012 13:08, Tobias Burnus wrote:
>> Only failing are:
>> lbound(x) / ubound(x) / shape(x)
>>
> Here is a draft for those.
> Lightly tested with print *, ...
>
Better with the tests.
$ ./test1
1 1
3 8
3 8
$ ./test2
11 101
13 108
3 8
[-- Attachment #2: test1.f90 --]
[-- Type: text/x-fortran, Size: 224 bytes --]
program test
integer :: a(1:3,-2:5)
call foo(a)
contains
subroutine foo(arg)
integer :: arg(..)
print *, lbound(arg)
print *, ubound(arg)
print *, shape(arg)
end subroutine foo
end program test
[-- Attachment #3: test2.f90 --]
[-- Type: text/x-fortran, Size: 434 bytes --]
program test
integer :: a(1:3,-2:5)
integer, allocatable :: b(:,:)
b = foo(a)
print *,b(:,1)
print *,b(:,2)
print *,b(:,3)
contains
function foo(arg) result(res)
integer :: arg(..)
integer, allocatable :: res(:,:)
allocate(res(rank(arg), 3))
res(:,1) = lbound(arg) + (/ 10, 100 /)
res(:,2) = (/ 10, 100 /) + ubound(arg)
res(:,3) = shape(arg)
end function foo
end program test
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-26 15:14 ` Mikael Morin
@ 2012-07-26 15:32 ` Tobias Burnus
2012-07-27 17:35 ` Mikael Morin
0 siblings, 1 reply; 11+ messages in thread
From: Tobias Burnus @ 2012-07-26 15:32 UTC (permalink / raw)
To: Mikael Morin; +Cc: gcc patches, gfortran
On 07/26/2012 05:12 PM, Mikael Morin wrote:
> On 26/07/2012 16:53, Mikael Morin wrote:
>> Here is a draft for those. Lightly tested with print *, ...
Looks rather nice. The output for test1 is also good:
integer :: a(1:3,-2:5)
gives
lbound(arg) == [1, 1]
ubound(arg) == [3, 8]
shape(arg) == [3, 8]
However, if the dummy is allocatable or a pointer, the result should be:
lbound(arg) == [1, -2]
ubound(arg) == [3, 5]
shape(arg) == [3, 8]
which your second test case doesn't give. (At least that's how I understand TS and F2008.)
Except for that issue, I like your patch. Thanks!
Tobias
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-26 15:32 ` Tobias Burnus
@ 2012-07-27 17:35 ` Mikael Morin
2012-08-01 10:01 ` Tobias Burnus
0 siblings, 1 reply; 11+ messages in thread
From: Mikael Morin @ 2012-07-27 17:35 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 1205 bytes --]
On 26/07/2012 17:32, Tobias Burnus wrote:
> On 07/26/2012 05:12 PM, Mikael Morin wrote:
>> On 26/07/2012 16:53, Mikael Morin wrote:
>>> Here is a draft for those. Lightly tested with print *, ...
>
> Looks rather nice. The output for test1 is also good:
>
> integer :: a(1:3,-2:5)
> gives
> lbound(arg) == [1, 1]
> ubound(arg) == [3, 8]
> shape(arg) == [3, 8]
>
> However, if the dummy is allocatable or a pointer, the result should be:
>
> lbound(arg) == [1, -2]
> ubound(arg) == [3, 5]
> shape(arg) == [3, 8]
>
> which your second test case doesn't give.
Hello,
do you have a test case exhibiting the problem?
It seems fine to me.
$ ./test1
1 1
3 8
3 8
1 1
3 8
3 8
1 -2
3 5
3 8
1 -2
3 5
3 8
./test2
11 101
13 108
3 8
11 97
12 106
2 10
13 99
15 110
3 12
[-- Attachment #2: test1.f90 --]
[-- Type: text/x-fortran, Size: 632 bytes --]
program test
integer :: a(1:3,-2:5)
integer, allocatable :: b(:,:)
call foo(a)
allocate(b(1:3,-2:5))
call foo(b)
call bar(b)
call baz(b)
contains
subroutine foo(arg)
integer :: arg(..)
print *, lbound(arg)
print *, ubound(arg)
print *, shape(arg)
end subroutine foo
subroutine bar(arg)
integer, allocatable :: arg(:,:)
print *, lbound(arg)
print *, ubound(arg)
print *, shape(arg)
end subroutine bar
subroutine baz(arg)
integer, allocatable :: arg(..)
print *, lbound(arg)
print *, ubound(arg)
print *, shape(arg)
end subroutine baz
end program test
[-- Attachment #3: test2.f90 --]
[-- Type: text/x-fortran, Size: 1239 bytes --]
program test
integer :: a(1:3,-2:5)
integer, allocatable :: b(:,:)
integer, allocatable :: c(:,:)
integer, pointer :: d(:,:)
b = foo(a)
print *,b(:,1)
print *,b(:,2)
print *,b(:,3)
allocate(c(1:2,-3:6))
b = bar(c)
print *,b(:,1)
print *,b(:,2)
print *,b(:,3)
allocate(d(3:5,-1:10))
b = baz(d)
print *,b(:,1)
print *,b(:,2)
print *,b(:,3)
contains
function foo(arg) result(res)
integer :: arg(..)
integer, allocatable :: res(:,:)
allocate(res(rank(arg), 3))
res(:,1) = lbound(arg) + (/ 10, 100 /)
res(:,2) = (/ 10, 100 /) + ubound(arg)
res(:,3) = shape(arg)
end function foo
function bar(arg) result(res)
integer, allocatable :: arg(..)
integer, allocatable :: res(:,:)
allocate(res(rank(arg), 3))
res(:,1) = lbound(arg) + (/ 10, 100 /)
res(:,2) = (/ 10, 100 /) + ubound(arg)
res(:,3) = shape(arg)
end function bar
function baz(arg) result(res)
integer, pointer :: arg(..)
integer, allocatable :: res(:,:)
allocate(res(rank(arg), 3))
res(:,1) = lbound(arg) + (/ 10, 100 /)
res(:,2) = (/ 10, 100 /) + ubound(arg)
res(:,3) = shape(arg)
end function baz
end program test
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-07-27 17:35 ` Mikael Morin
@ 2012-08-01 10:01 ` Tobias Burnus
2012-08-01 11:40 ` Mikael Morin
0 siblings, 1 reply; 11+ messages in thread
From: Tobias Burnus @ 2012-08-01 10:01 UTC (permalink / raw)
To: Mikael Morin; +Cc: gcc patches, gfortran
On 07/27/2012 07:26 PM, Mikael Morin wrote:
> do you have a test case exhibiting the problem? It seems fine to me.
Your second test case was too convoluted for me - and as I wasn't at
home, I couldn't test it. I now believe that your patch is okay; I will
later formally review it.
Do you intent to wrap it for final inclusion? I think it only lacks a
dejaGNUified test case and a changelog.
* * *
However, I found another spot where one needs to have a scalarizer;
possibly a poor man's version is enough. Namely INTENT(OUT) handling. Do
you have an idea how to best handle that case?
program test
implicit none
type t
integer, allocatable :: a
end type t
type(t) :: b(4,6)
integer :: i, j
do j = 1, 6
do i = 1, 4
allocate (b(i,j)%a)
end do
end do
call sub (b(::2,::3))
do j = 1, 6
do i = 1, 4
print *, i, j, allocated (b(i,j)%a)
! if (allocated (b(i,j)%a) .neqv. (mod (i-1,2) /= 0 .or. mod
(j-1,3) /= 0))&
! call abort ()
end do
end do
contains
subroutine sub (x)
type(t), intent(out) :: x(..)
end subroutine sub
end program test
Tobias
PS: Note to self: Reject passing an assumed-size array to an INTENT(OUT)
assumed-rank array, at least if it is "polymorphic, finalizable, of a
type with an allocatable ultimate component, or of a type for which
default initialization is specified." [TS29113 seems to allow it, but
one needs some check similar to F2008's C534. A constraint is not enough
as it doesn't cover all cases, but the rest is the user's responsibility.]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-08-01 10:01 ` Tobias Burnus
@ 2012-08-01 11:40 ` Mikael Morin
2012-08-01 12:38 ` Tobias Burnus
0 siblings, 1 reply; 11+ messages in thread
From: Mikael Morin @ 2012-08-01 11:40 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc patches, gfortran
On 01/08/2012 12:00, Tobias Burnus wrote:
> On 07/27/2012 07:26 PM, Mikael Morin wrote:
>> do you have a test case exhibiting the problem? It seems fine to me.
>
> Your second test case was too convoluted for me - and as I wasn't at
> home, I couldn't test it. I now believe that your patch is okay; I will
> later formally review it.
I will formally ask for it. ;-)
>
> Do you intent to wrap it for final inclusion? I think it only lacks a
> dejaGNUified test case and a changelog.
Will do.
>
> * * *
>
> However, I found another spot where one needs to have a scalarizer;
> possibly a poor man's version is enough. Namely INTENT(OUT) handling.
Indeed.
> Do you have an idea how to best handle that case?
It seems some new code is necessary. I don't know how well it will
fit/reuse the existing though.
I have been thinking about rewriting the scalarizer in a way that would
need less bookkeeping to make things work. Nothing near a patch though,
and it's not something for 4.8. Anyway, here is the interface I had in mind:
gfc_init_loopinfo (loopinfo);
/* generate the code. */
gfc_conv_expr (loopinfo, expr1);
gfc_conv_expr (loopinfo, expr2);
/* etc, do something, putting loopinfo every time as parameter so that
it is populated appropriately... and then: */
loopblock = gfc_scalarize (loopinfo);
the gfc_scalarize could have a big `if' in it distinguishing known rank
from assumed rank.
Maybe we could take the opportunity to make a seed for a new scalarizer.
Mikael
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-08-01 11:40 ` Mikael Morin
@ 2012-08-01 12:38 ` Tobias Burnus
2012-08-01 12:52 ` Richard Guenther
0 siblings, 1 reply; 11+ messages in thread
From: Tobias Burnus @ 2012-08-01 12:38 UTC (permalink / raw)
To: Mikael Morin; +Cc: gcc patches, gfortran
On 08/01/2012 01:37 PM, Mikael Morin wrote:
>> However, I found another spot where one needs to have a scalarizer;
>> possibly a poor man's version is enough. Namely INTENT(OUT) handling.
> Indeed.
>> Do you have an idea how to best handle that case?
> It seems some new code is necessary. I don't know how well it will
> fit/reuse the existing though.
I think we should try to get this working in some way for 4.8 as
assumed-rank arrays will be used for the finalization wrapper - and it
would be awesome to have FINAL support in 4.8.
Background: As it is unknown (at compile time) whether a polymorphic
variable has no final subroutines or one for that rank or an elemental
one (or some but no suitable ones) - and as there could be a different
combination for the parent type, the current plan is to add a _final
proc-pointer to the vtable, which points to a final wrapper procedure
for that type. It takes (at least for arrays) an assumed-rank array and
dispatches the calls based on the rank; for an elemental final
subroutine, it has to "scalarize it". [It's simple to add a special case
as the array is contiguous - one just needs to "call
elemental(base_address + i*elem_size)", where i =
1,size(assumed-size-array).]
And for finalization, it would be great if one could use the INTENT(OUT)
support. One could alternatively implement it manually on the gfortran
AST level (gfc_code/gfc_expr) by walking through the derived type or one
could implement a simplified version, making use of the contiguity of
the finalized variable.
> I have been thinking about rewriting the scalarizer in a way that would
> need less bookkeeping to make things work. Nothing near a patch though,
> and it's not something for 4.8.
I think it would be good to base it on the new array descriptor, which
we hopefully have by that time. Additionally, we should consider to support:
a) ARRAY_RANGE_REF: That's probably somewhat independent of
scalarization, but replaces it in some cases:
A(:,:,5) = B(:)
can be implemented as ARRAY_RANGE_REF, if the memory is contiguous; one
just passes an offset and (via the decl) the size of the array
(section). See trans-expr.c for one example. A range ref is better than
a memcpy/memmove or a loop - as the first looses the data type and some
alias information and the second represents the structure in a more
convoluted way. Either could be recovered by the middle end, but it
currently isn't and doing it correctly from the beginning makes the ME
life easier.
b) Middle-end arrays. Richard made an initial patch, cf.
http://gcc.gnu.org/wiki/GCCGathering2011Fortran . It probably needs some
polishing and some optimizations have to be implemented, but then it
should work and allow for further optimizations. [Description in the
wiki might be partially wrong; blame me - and correct it, if you find
something.]
I think the latter requires also some thinking about how to handle
arrays internally: In that case, the array has - at least for the
scalarization - more than one rank (for the ME) while gfortran normally
folds everything to rank-1 arrays. Additionally, one needs to think
about the case where the array has nonunit strides, i.e. where the
leftmost stride is not sizeof(declared type) but larger by a noninteger
amount. (e.g. passing a polymorphic array to a TYPE.)
Tobias
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs
2012-08-01 12:38 ` Tobias Burnus
@ 2012-08-01 12:52 ` Richard Guenther
0 siblings, 0 replies; 11+ messages in thread
From: Richard Guenther @ 2012-08-01 12:52 UTC (permalink / raw)
To: Tobias Burnus; +Cc: Mikael Morin, gcc patches, gfortran
On Wed, Aug 1, 2012 at 2:37 PM, Tobias Burnus <burnus@net-b.de> wrote:
> On 08/01/2012 01:37 PM, Mikael Morin wrote:
>>>
>>> However, I found another spot where one needs to have a scalarizer;
>>> possibly a poor man's version is enough. Namely INTENT(OUT) handling.
>>
>> Indeed.
>>>
>>> Do you have an idea how to best handle that case?
>>
>> It seems some new code is necessary. I don't know how well it will
>> fit/reuse the existing though.
>
>
> I think we should try to get this working in some way for 4.8 as
> assumed-rank arrays will be used for the finalization wrapper - and it would
> be awesome to have FINAL support in 4.8.
>
> Background: As it is unknown (at compile time) whether a polymorphic
> variable has no final subroutines or one for that rank or an elemental one
> (or some but no suitable ones) - and as there could be a different
> combination for the parent type, the current plan is to add a _final
> proc-pointer to the vtable, which points to a final wrapper procedure for
> that type. It takes (at least for arrays) an assumed-rank array and
> dispatches the calls based on the rank; for an elemental final subroutine,
> it has to "scalarize it". [It's simple to add a special case as the array is
> contiguous - one just needs to "call elemental(base_address + i*elem_size)",
> where i = 1,size(assumed-size-array).]
>
> And for finalization, it would be great if one could use the INTENT(OUT)
> support. One could alternatively implement it manually on the gfortran AST
> level (gfc_code/gfc_expr) by walking through the derived type or one could
> implement a simplified version, making use of the contiguity of the
> finalized variable.
>
>
>
>> I have been thinking about rewriting the scalarizer in a way that would
>> need less bookkeeping to make things work. Nothing near a patch though,
>> and it's not something for 4.8.
>
>
> I think it would be good to base it on the new array descriptor, which we
> hopefully have by that time. Additionally, we should consider to support:
>
> a) ARRAY_RANGE_REF: That's probably somewhat independent of scalarization,
> but replaces it in some cases:
> A(:,:,5) = B(:)
> can be implemented as ARRAY_RANGE_REF, if the memory is contiguous; one just
> passes an offset and (via the decl) the size of the array (section). See
> trans-expr.c for one example. A range ref is better than a memcpy/memmove or
> a loop - as the first looses the data type and some alias information and
> the second represents the structure in a more convoluted way. Either could
> be recovered by the middle end, but it currently isn't and doing it
> correctly from the beginning makes the ME life easier.
>
> b) Middle-end arrays. Richard made an initial patch, cf.
> http://gcc.gnu.org/wiki/GCCGathering2011Fortran . It probably needs some
> polishing and some optimizations have to be implemented, but then it should
> work and allow for further optimizations. [Description in the wiki might be
> partially wrong; blame me - and correct it, if you find something.]
Well, I wouldn't concentrate on this one ;)
> I think the latter requires also some thinking about how to handle arrays
> internally: In that case, the array has - at least for the scalarization -
> more than one rank (for the ME) while gfortran normally folds everything to
> rank-1 arrays. Additionally, one needs to think about the case where the
> array has nonunit strides, i.e. where the leftmost stride is not
> sizeof(declared type) but larger by a noninteger amount. (e.g. passing a
> polymorphic array to a TYPE.)
c) Do _not_ fold everything to rank-1 arrays (this makes data
dependence analysis
harder). If you know the rank of an array use an intermediate array
pointer type
to access the data, like the following C example:
void foo (void *data, int n, int m)
{
int (*a)[n][m] = (int (*)[n][m]) data;
int i, j;
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
(*a)[i][j] = 0;
}
d) Think about Frontend optimizations again - using the ISL part of GRAPHITE
on the GFortran IL, possibly driving the scalarizer with the result.
Richard.
> Tobias
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-08-01 12:52 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-20 10:20 [Patch, Fortran] assumed-rank some bound intrinsics support, fix failures and improve diagnostcs Tobias Burnus
2012-07-21 10:41 ` Mikael Morin
2012-07-21 11:08 ` Tobias Burnus
2012-07-26 14:55 ` Mikael Morin
2012-07-26 15:14 ` Mikael Morin
2012-07-26 15:32 ` Tobias Burnus
2012-07-27 17:35 ` Mikael Morin
2012-08-01 10:01 ` Tobias Burnus
2012-08-01 11:40 ` Mikael Morin
2012-08-01 12:38 ` Tobias Burnus
2012-08-01 12:52 ` Richard Guenther
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).