Commit 22fa926f by Mikael Morin

bound simplification refactoring

gcc/fortran/
	* simplify.c (simplify_bound_dim): Don't check for emptyness
	in the case of cobound simplification.  Factor lower/upper
	bound differenciation before the actual simplification.
	(simplify_bound): Remove assumed shape specific simplification.  
	Don't give up early for the lbound of an assumed shape.
gcc/testsuite/
	* gfortran.dg/bound_simplification_5.f90: New.

From-SVN: r222979
parent edff0c06
2015-05-10 Mikael Morin <mikael@gcc.gnu.org>
* simplify.c (simplify_bound_dim): Don't check for emptyness
in the case of cobound simplification. Factor lower/upper
bound differenciation before the actual simplification.
(simplify_bound): Remove assumed shape specific simplification.
Don't give up early for the lbound of an assumed shape.
2015-05-09 Mikael Morin <mikael@gcc.gnu.org> 2015-05-09 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/65894 PR fortran/65894
......
...@@ -3340,29 +3340,43 @@ simplify_bound_dim (gfc_expr *array, gfc_expr *kind, int d, int upper, ...@@ -3340,29 +3340,43 @@ simplify_bound_dim (gfc_expr *array, gfc_expr *kind, int d, int upper,
/* Then, we need to know the extent of the given dimension. */ /* Then, we need to know the extent of the given dimension. */
if (coarray || (ref->u.ar.type == AR_FULL && !ref->next)) if (coarray || (ref->u.ar.type == AR_FULL && !ref->next))
{ {
gfc_expr *declared_bound;
int empty_bound;
bool constant_lbound, constant_ubound;
l = as->lower[d-1]; l = as->lower[d-1];
u = as->upper[d-1]; u = as->upper[d-1];
if (l->expr_type != EXPR_CONSTANT || u == NULL gcc_assert (l != NULL);
|| u->expr_type != EXPR_CONSTANT)
constant_lbound = l->expr_type == EXPR_CONSTANT;
constant_ubound = u && u->expr_type == EXPR_CONSTANT;
empty_bound = upper ? 0 : 1;
declared_bound = upper ? u : l;
if ((!upper && !constant_lbound)
|| (upper && !constant_ubound))
goto returnNull; goto returnNull;
if (mpz_cmp (l->value.integer, u->value.integer) > 0) if (!coarray)
{ {
/* Zero extent. */ /* For {L,U}BOUND, the value depends on whether the array
if (upper) is empty. We can nevertheless simplify if the declared bound
mpz_set_si (result->value.integer, 0); has the same value as that of an empty array, in which case
the result isn't dependent on the array emptyness. */
if (mpz_cmp_si (declared_bound->value.integer, empty_bound) == 0)
mpz_set_si (result->value.integer, empty_bound);
else if (!constant_lbound || !constant_ubound)
/* Array emptyness can't be determined, we can't simplify. */
goto returnNull;
else if (mpz_cmp (l->value.integer, u->value.integer) > 0)
mpz_set_si (result->value.integer, empty_bound);
else else
mpz_set_si (result->value.integer, 1); mpz_set (result->value.integer, declared_bound->value.integer);
} }
else else
{ mpz_set (result->value.integer, declared_bound->value.integer);
/* Nonzero extent. */
if (upper)
mpz_set (result->value.integer, u->value.integer);
else
mpz_set (result->value.integer, l->value.integer);
}
} }
else else
{ {
...@@ -3442,43 +3456,16 @@ simplify_bound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper) ...@@ -3442,43 +3456,16 @@ simplify_bound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper)
done: done:
/* If the array shape is assumed shape or explicit, we can simplify lbound if (as && (as->type == AS_DEFERRED || as->type == AS_ASSUMED_RANK
to 1 if the given lower bound is one because this matches what lbound || (as->type == AS_ASSUMED_SHAPE && upper)))
should return for an empty array. */
if (!upper && as && dim && dim->expr_type == EXPR_CONSTANT
&& (as->type == AS_ASSUMED_SHAPE || as->type == AS_EXPLICIT)
&& ref->u.ar.type != AR_SECTION)
{
/* Watch out for allocatable or pointer dummy arrays, they can have
lower bounds that are not equal to one. */
if (!(array->symtree && array->symtree->n.sym
&& (array->symtree->n.sym->attr.allocatable
|| array->symtree->n.sym->attr.pointer)))
{
unsigned long int ndim;
gfc_expr *lower, *res;
ndim = mpz_get_si (dim->value.integer) - 1;
lower = as->lower[ndim];
if (lower->expr_type == EXPR_CONSTANT
&& mpz_cmp_si (lower->value.integer, 1) == 0)
{
res = gfc_copy_expr (lower);
if (kind)
{
int nkind = mpz_get_si (kind->value.integer);
res->ts.kind = nkind;
}
return res;
}
}
}
if (as && (as->type == AS_DEFERRED || as->type == AS_ASSUMED_SHAPE
|| as->type == AS_ASSUMED_RANK))
return NULL; return NULL;
gcc_assert (!as
|| (as->type != AS_DEFERRED
&& array->expr_type == EXPR_VARIABLE
&& !array->symtree->n.sym->attr.allocatable
&& !array->symtree->n.sym->attr.pointer));
if (dim == NULL) if (dim == NULL)
{ {
/* Multi-dimensional bounds. */ /* Multi-dimensional bounds. */
......
2015-05-10 Mikael Morin <mikael@gcc.gnu.org>
* gfortran.dg/bound_simplification_5.f90: New.
2015-05-09 Jason Merrill <jason@redhat.com> 2015-05-09 Jason Merrill <jason@redhat.com>
* lib/target-supports.exp (cxx_default): New global. * lib/target-supports.exp (cxx_default): New global.
......
! { dg-do run }
! { dg-additional-options "-fcoarray=single -fdump-tree-original" }
!
! Check that {L,U}{,CO}BOUND intrinsics are properly simplified.
!
implicit none
type :: t
integer :: c
end type t
type(t) :: d(3:8) = t(7)
type(t) :: e[5:9,-1:*]
type(t) :: h(3), j(4), k(0)
!Test full arrays vs subarrays
if (lbound(d, 1) /= 3) call abort
if (lbound(d(3:5), 1) /= 1) call abort
if (lbound(d%c, 1) /= 1) call abort
if (ubound(d, 1) /= 8) call abort
if (ubound(d(3:5), 1) /= 3) call abort
if (ubound(d%c, 1) /= 6) call abort
if (lcobound(e, 1) /= 5) call abort
if (lcobound(e%c, 1) /= 5) call abort
if (lcobound(e, 2) /= -1) call abort
if (lcobound(e%c, 2) /= -1) call abort
if (ucobound(e, 1) /= 9) call abort
if (ucobound(e%c, 1) /= 9) call abort
! no simplification for ucobound(e{,%c}, dim=2)
if (any(lbound(d ) /= [3])) call abort
if (any(lbound(d(3:5)) /= [1])) call abort
if (any(lbound(d%c ) /= [1])) call abort
if (any(ubound(d ) /= [8])) call abort
if (any(ubound(d(3:5)) /= [3])) call abort
if (any(ubound(d%c ) /= [6])) call abort
if (any(lcobound(e ) /= [5, -1])) call abort
if (any(lcobound(e%c) /= [5, -1])) call abort
! no simplification for ucobound(e{,%c})
call test_empty_arrays(h, j, k)
contains
subroutine test_empty_arrays(a, c, d)
type(t) :: a(:), c(-3:0), d(3:1)
type(t) :: f(4:2), g(0:6)
if (lbound(a, 1) /= 1) call abort
if (lbound(c, 1) /= -3) call abort
if (lbound(d, 1) /= 1) call abort
if (lbound(f, 1) /= 1) call abort
if (lbound(g, 1) /= 0) call abort
if (ubound(c, 1) /= 0) call abort
if (ubound(d, 1) /= 0) call abort
if (ubound(f, 1) /= 0) call abort
if (ubound(g, 1) /= 6) call abort
if (any(lbound(a) /= [ 1])) call abort
if (any(lbound(c) /= [-3])) call abort
if (any(lbound(d) /= [ 1])) call abort
if (any(lbound(f) /= [ 1])) call abort
if (any(lbound(g) /= [ 0])) call abort
if (any(ubound(c) /= [0])) call abort
if (any(ubound(d) /= [0])) call abort
if (any(ubound(f) /= [0])) call abort
if (any(ubound(g) /= [6])) call abort
end subroutine
end
! { dg-final { scan-tree-dump-not "abort" "original" } }
! { dg-final { cleanup-tree-dump "original" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment