* trans-array.c (gfc_build_constant_array_constructor): When the
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 18 Feb 2007 20:05:00 +0000 (20:05 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 18 Feb 2007 20:05:00 +0000 (20:05 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122103 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/fortran/ChangeLog
gcc/fortran/trans-array.c
gcc/fortran/trans-intrinsic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/array_constructor_15.f90 [new file with mode: 0644]

index 43c10ee..388bfd6 100644 (file)
@@ -1,4 +1,18 @@
 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>
 
         PR fortran/30400
@@ -11,7 +25,7 @@
 
        PR fortran/30793
        * 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>
            Brooks Moses  <brooks.moses@codesourcery.com>
index 64ea9d6..683c8bd 100644 (file)
@@ -1453,7 +1453,7 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
   gfc_constructor *c;
   gfc_array_spec as;
   gfc_se se;
-
+  int i;
 
   /* First traverse the constructor list, converting the constants
      to tree to build an initializer.  */
@@ -1478,10 +1478,21 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
 
   memset (&as, 0, sizeof (gfc_array_spec));
 
-  as.rank = 1;
+  as.rank = expr->rank;
   as.type = AS_EXPLICIT;
-  as.lower[0] = gfc_int_expr (0);
-  as.upper[0] = gfc_int_expr (nelem - 1);
+  if (!expr->shape)
+    {
+      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);
 
   init = build_constructor_from_list (tmptype, nreverse (list));
@@ -1512,6 +1523,7 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
 {
   gfc_ss_info *info;
   tree tmp;
+  int i;
 
   tmp = gfc_build_constant_array_constructor (ss->expr, type);
 
@@ -1522,16 +1534,54 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
   info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
                              loop->from[0]);
 
-  info->delta[0] = gfc_index_zero_node;
-  info->start[0] = gfc_index_zero_node;
-  info->end[0] = gfc_index_zero_node;
-  info->stride[0] = gfc_index_one_node;
-  info->dim[0] = 0;
+  for (i = 0; i < info->dimen; i++)
+    {
+      info->delta[i] = gfc_index_zero_node;
+      info->start[i] = gfc_index_zero_node;
+      info->end[i] = gfc_index_zero_node;
+      info->stride[i] = gfc_index_one_node;
+      info->dim[i] = i;
+    }
 
   if (info->dimen > loop->temp_dim)
     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
    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)
     }
 
   /* Special case constant array constructors.  */
-  if (!dynamic
-      && loop->dimen == 1
-      && INTEGER_CST_P (loop->from[0])
-      && INTEGER_CST_P (loop->to[0]))
+  if (!dynamic)
     {
       unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
       if (nelem > 0)
        {
-         tree diff = fold_build2 (MINUS_EXPR, gfc_array_index_type,
-                                  loop->to[0], loop->from[0]);
-         if (compare_tree_int (diff, nelem - 1) == 0)
+         tree size = constant_array_constructor_loop_size (loop);
+         if (size && compare_tree_int (size, nelem) == 0)
            {
              gfc_trans_constant_array_constructor (loop, ss, type);
              return;
index e6bc46f..c041b63 100644 (file)
@@ -1604,8 +1604,8 @@ gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, int op)
   gfc_conv_expr_val (&arrayse, actual->expr);
 
   gfc_add_block_to_block (&body, &arrayse.pre);
-  tmp = build2 (op, boolean_type_node, arrayse.expr,
-               build_int_cst (TREE_TYPE (arrayse.expr), 0));
+  tmp = fold_build2 (op, boolean_type_node, arrayse.expr,
+                    build_int_cst (TREE_TYPE (arrayse.expr), 0));
   tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt ());
   gfc_add_expr_to_block (&body, tmp);
   gfc_add_block_to_block (&body, &arrayse.post);
index 5870a68..3151a7d 100644 (file)
@@ -1,5 +1,9 @@
 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.
 
 2007-02-18  Eric Botcazou  <ebotcazou@adacore.com>
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_15.f90 b/gcc/testsuite/gfortran.dg/array_constructor_15.f90
new file mode 100644 (file)
index 0000000..7126016
--- /dev/null
@@ -0,0 +1,7 @@
+! { 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" } }