Commit 61a04b5b by Roger Sayle

trans-array.c (gfc_build_constant_array_constructor): When the shape of the constructor is known...


	* trans-array.c (gfc_build_constant_array_constructor): When the
	shape of the constructor is known, use that to construct the
	gfc_array_spec.
	(gfc_trans_constant_array_constructor): Initialize the "info"
	information for all of the dimensions of the array constructor.
	(constant_array_constructor_loop_size): New function.
	(gfc_trans_array_constructor): Use it to determine whether a
	loop is suitable for "constant array constructor" optimization.

	* trans-intrinsic.c (gfc_conv_intrinsic_anyall): Use fold_build2
	instead of build2, to avoid conditions like "(a != b) != 0".

	* gfortran.dg/array_constructor_15.f90: New test case.

From-SVN: r122103
parent 9bffa171
2007-02-18 Roger Sayle <roger@eyesopen.com> 2007-02-18 Roger Sayle <roger@eyesopen.com>
* trans-array.c (gfc_build_constant_array_constructor): When the
shape of the constructor is known, use that to construct the
gfc_array_spec.
(gfc_trans_constant_array_constructor): Initialize the "info"
information for all of the dimensions of the array constructor.
(constant_array_constructor_loop_size): New function.
(gfc_trans_array_constructor): Use it to determine whether a
loop is suitable for "constant array constructor" optimization.
* trans-intrinsic.c (gfc_conv_intrinsic_anyall): Use fold_build2
instead of build2, to avoid conditions like "(a != b) != 0".
2007-02-18 Roger Sayle <roger@eyesopen.com>
Paul Thomas <pault@gcc.gnu.org> Paul Thomas <pault@gcc.gnu.org>
PR fortran/30400 PR fortran/30400
...@@ -11,7 +25,7 @@ ...@@ -11,7 +25,7 @@
PR fortran/30793 PR fortran/30793
* trans-decl.c (gfc_generate_function_code): Do not initialize * trans-decl.c (gfc_generate_function_code): Do not initialize
pointers to derived components. pointers to derived components.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com> 2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com> Brooks Moses <brooks.moses@codesourcery.com>
......
...@@ -1453,7 +1453,7 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type) ...@@ -1453,7 +1453,7 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
gfc_constructor *c; gfc_constructor *c;
gfc_array_spec as; gfc_array_spec as;
gfc_se se; gfc_se se;
int i;
/* First traverse the constructor list, converting the constants /* First traverse the constructor list, converting the constants
to tree to build an initializer. */ to tree to build an initializer. */
...@@ -1478,10 +1478,21 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type) ...@@ -1478,10 +1478,21 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
memset (&as, 0, sizeof (gfc_array_spec)); memset (&as, 0, sizeof (gfc_array_spec));
as.rank = 1; as.rank = expr->rank;
as.type = AS_EXPLICIT; as.type = AS_EXPLICIT;
as.lower[0] = gfc_int_expr (0); if (!expr->shape)
as.upper[0] = gfc_int_expr (nelem - 1); {
as.lower[0] = gfc_int_expr (0);
as.upper[0] = gfc_int_expr (nelem - 1);
}
else
for (i = 0; i < expr->rank; i++)
{
int tmp = (int) mpz_get_si (expr->shape[i]);
as.lower[i] = gfc_int_expr (0);
as.upper[i] = gfc_int_expr (tmp - 1);
}
tmptype = gfc_get_nodesc_array_type (type, &as, 3); tmptype = gfc_get_nodesc_array_type (type, &as, 3);
init = build_constructor_from_list (tmptype, nreverse (list)); init = build_constructor_from_list (tmptype, nreverse (list));
...@@ -1512,6 +1523,7 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop, ...@@ -1512,6 +1523,7 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
{ {
gfc_ss_info *info; gfc_ss_info *info;
tree tmp; tree tmp;
int i;
tmp = gfc_build_constant_array_constructor (ss->expr, type); tmp = gfc_build_constant_array_constructor (ss->expr, type);
...@@ -1522,16 +1534,54 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop, ...@@ -1522,16 +1534,54 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type, info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
loop->from[0]); loop->from[0]);
info->delta[0] = gfc_index_zero_node; for (i = 0; i < info->dimen; i++)
info->start[0] = gfc_index_zero_node; {
info->end[0] = gfc_index_zero_node; info->delta[i] = gfc_index_zero_node;
info->stride[0] = gfc_index_one_node; info->start[i] = gfc_index_zero_node;
info->dim[0] = 0; info->end[i] = gfc_index_zero_node;
info->stride[i] = gfc_index_one_node;
info->dim[i] = i;
}
if (info->dimen > loop->temp_dim) if (info->dimen > loop->temp_dim)
loop->temp_dim = info->dimen; loop->temp_dim = info->dimen;
} }
/* Helper routine of gfc_trans_array_constructor to determine if the
bounds of the loop specified by LOOP are constant and simple enough
to use with gfc_trans_constant_array_constructor. Returns the
the iteration count of the loop if suitable, and NULL_TREE otherwise. */
static tree
constant_array_constructor_loop_size (gfc_loopinfo * loop)
{
tree size = gfc_index_one_node;
tree tmp;
int i;
for (i = 0; i < loop->dimen; i++)
{
/* If the bounds aren't constant, return NULL_TREE. */
if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
return NULL_TREE;
if (!integer_zerop (loop->from[i]))
{
/* Only allow non-zero "from" in one-dimensional arrays. */
if (loop->dimen != 1)
return NULL_TREE;
tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
loop->to[i], loop->from[i]);
}
else
tmp = loop->to[i];
tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
tmp, gfc_index_one_node);
size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
}
return size;
}
/* Array constructors are handled by constructing a temporary, then using that /* Array constructors are handled by constructing a temporary, then using that
within the scalarization loop. This is not optimal, but seems by far the within the scalarization loop. This is not optimal, but seems by far the
...@@ -1584,17 +1634,13 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss) ...@@ -1584,17 +1634,13 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
} }
/* Special case constant array constructors. */ /* Special case constant array constructors. */
if (!dynamic if (!dynamic)
&& loop->dimen == 1
&& INTEGER_CST_P (loop->from[0])
&& INTEGER_CST_P (loop->to[0]))
{ {
unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c); unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
if (nelem > 0) if (nelem > 0)
{ {
tree diff = fold_build2 (MINUS_EXPR, gfc_array_index_type, tree size = constant_array_constructor_loop_size (loop);
loop->to[0], loop->from[0]); if (size && compare_tree_int (size, nelem) == 0)
if (compare_tree_int (diff, nelem - 1) == 0)
{ {
gfc_trans_constant_array_constructor (loop, ss, type); gfc_trans_constant_array_constructor (loop, ss, type);
return; return;
......
...@@ -1604,8 +1604,8 @@ gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, int op) ...@@ -1604,8 +1604,8 @@ gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, int op)
gfc_conv_expr_val (&arrayse, actual->expr); gfc_conv_expr_val (&arrayse, actual->expr);
gfc_add_block_to_block (&body, &arrayse.pre); gfc_add_block_to_block (&body, &arrayse.pre);
tmp = build2 (op, boolean_type_node, arrayse.expr, tmp = fold_build2 (op, boolean_type_node, arrayse.expr,
build_int_cst (TREE_TYPE (arrayse.expr), 0)); build_int_cst (TREE_TYPE (arrayse.expr), 0));
tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt ()); tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt ());
gfc_add_expr_to_block (&body, tmp); gfc_add_expr_to_block (&body, tmp);
gfc_add_block_to_block (&body, &arrayse.post); gfc_add_block_to_block (&body, &arrayse.post);
......
2007-02-18 Roger Sayle <roger@eyesopen.com> 2007-02-18 Roger Sayle <roger@eyesopen.com>
* gfortran.dg/array_constructor_15.f90: New test case.
2007-02-18 Roger Sayle <roger@eyesopen.com>
* gfortran.dg/forall_10.f90: New test case. * gfortran.dg/forall_10.f90: New test case.
2007-02-18 Eric Botcazou <ebotcazou@adacore.com> 2007-02-18 Eric Botcazou <ebotcazou@adacore.com>
! { dg-do compile }
! { dg-options "-O2 -fdump-tree-original" }
integer :: x(2,2)
if (any(x(:,:) .ne. reshape ((/ 3, 1, 4, 1 /), (/ 2, 2 /)))) call abort ()
end
! { dg-final { scan-tree-dump-times "atmp" 0 "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