trans-array.c (toplevel): Include gimple.h.
authorMichael Matz <matz@suse.de>
Fri, 15 Apr 2011 21:48:19 +0000 (21:48 +0000)
committerMichael Matz <matz@gcc.gnu.org>
Fri, 15 Apr 2011 21:48:19 +0000 (21:48 +0000)
* trans-array.c (toplevel): Include gimple.h.
(gfc_trans_allocate_array_storage): Check flag_stack_arrays,
properly expand variable length arrays.
(gfc_trans_auto_array_allocation): If flag_stack_arrays create
variable length decls and associate them with their scope.
* gfortran.h (gfc_option_t): Add flag_stack_arrays member.
* options.c (gfc_init_options): Handle -fstack_arrays option.
* lang.opt (fstack-arrays): Add option.
* invoke.texi (Code Gen Options): Document it.
* Make-lang.in (trans-array.o): Depend on GIMPLE_H.

From-SVN: r172524

gcc/fortran/ChangeLog
gcc/fortran/Make-lang.in
gcc/fortran/gfortran.h
gcc/fortran/invoke.texi
gcc/fortran/lang.opt
gcc/fortran/options.c
gcc/fortran/trans-array.c

index 5a8283f1f2660b5cf9aa18e3d07139c3dc8bdcfe..77426165b62346720a275f5789aa1c83ceaa8b6d 100644 (file)
@@ -1,3 +1,16 @@
+2011-04-15  Michael Matz  <matz@suse.de>
+
+       * trans-array.c (toplevel): Include gimple.h.
+       (gfc_trans_allocate_array_storage): Check flag_stack_arrays,
+       properly expand variable length arrays.
+       (gfc_trans_auto_array_allocation): If flag_stack_arrays create
+       variable length decls and associate them with their scope.
+       * gfortran.h (gfc_option_t): Add flag_stack_arrays member.
+       * options.c (gfc_init_options): Handle -fstack_arrays option.
+       * lang.opt (fstack-arrays): Add option.
+       * invoke.texi (Code Gen Options): Document it.
+       * Make-lang.in (trans-array.o): Depend on GIMPLE_H.
+
 2011-04-15  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/18918
index ac4401dde49f6ad9e0647d7d263ae68f92bce210..753221d272c13cbf54317d0d0b1ec187176eb54c 100644 (file)
@@ -353,7 +353,7 @@ fortran/trans-stmt.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
 fortran/trans-openmp.o: $(GFORTRAN_TRANS_DEPS)
 fortran/trans-io.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-io.h \
   fortran/ioparm.def
-fortran/trans-array.o: $(GFORTRAN_TRANS_DEPS)
+fortran/trans-array.o: $(GFORTRAN_TRANS_DEPS) $(GIMPLE_H)
 fortran/trans-intrinsic.o: $(GFORTRAN_TRANS_DEPS) fortran/mathbuiltins.def \
   gt-fortran-trans-intrinsic.h
 fortran/dependency.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
index 73c39669c4ca3bc8e42c7a9e5193fde6130bbdf1..c2c9d0548f8e34c72b03bb02943c0dd229f6af4d 100644 (file)
@@ -2221,6 +2221,7 @@ typedef struct
   int flag_d_lines;
   int gfc_flag_openmp;
   int flag_sign_zero;
+  int flag_stack_arrays;
   int flag_module_private;
   int flag_recursive;
   int flag_init_local_zero;
index 96beff58215bb9dfb5b434fb12d945d7d6403207..57f7313f4bd8b3271c6a5b7deaa0a595cec39a5b 100644 (file)
@@ -167,6 +167,7 @@ and warnings}.
 -fbounds-check -fcheck-array-temporaries  -fmax-array-constructor =@var{n} @gol
 -fcheck=@var{<all|array-temps|bounds|do|mem|pointer|recursion>} @gol
 -fcoarray=@var{<none|single|lib>} -fmax-stack-var-size=@var{n} @gol
+-fstack-arrays @gol
 -fpack-derived  -frepack-arrays  -fshort-enums  -fexternal-blas @gol
 -fblas-matmul-limit=@var{n} -frecursive -finit-local-zero @gol
 -finit-integer=@var{n} -finit-real=@var{<zero|inf|-inf|nan|snan>} @gol
@@ -1370,6 +1371,13 @@ Future versions of GNU Fortran may improve this behavior.
 
 The default value for @var{n} is 32768.
 
+@item -fstack-arrays
+@opindex @code{fstack-arrays}
+Adding this option will make the fortran compiler put all local arrays,
+even those of unknown size onto stack memory.  If your program uses very
+large local arrays it's possible that you'll have to extend your runtime
+limits for stack memory on some operating systems.
+
 @item -fpack-derived
 @opindex @code{fpack-derived}
 @cindex structure packing
index adc6dce6d1e4e8f50ff900348f324500c5d5b251..3055825047f3529e68361fd1e60b215ba7adc7ee 100644 (file)
@@ -462,6 +462,10 @@ fmax-stack-var-size=
 Fortran RejectNegative Joined UInteger
 -fmax-stack-var-size=<n>       Size in bytes of the largest array that will be put on the stack
 
+fstack-arrays
+Fortran
+Put all local arrays on stack.
+
 fmodule-private
 Fortran
 Set default accessibility of module entities to PRIVATE.
index 008346056a74aa9bf5a0adf7b3c6ea77d845f0eb..5e173088d941b48b5cfe0fd2cc210b50b1cb04d4 100644 (file)
@@ -124,6 +124,7 @@ gfc_init_options (unsigned int decoded_options_count,
 
   /* Default value of flag_max_stack_var_size is set in gfc_post_options.  */
   gfc_option.flag_max_stack_var_size = -2;
+  gfc_option.flag_stack_arrays = 0;
 
   gfc_option.flag_range_check = 1;
   gfc_option.flag_pack_derived = 0;
@@ -795,6 +796,10 @@ gfc_handle_option (size_t scode, const char *arg, int value,
       gfc_option.flag_max_stack_var_size = value;
       break;
 
+    case OPT_fstack_arrays:
+      gfc_option.flag_stack_arrays = value;
+      break;
+
     case OPT_fmodule_private:
       gfc_option.flag_module_private = value;
       break;
index 7c34b9865ea7e4347b2b8f5fd46ffbe80c63e7a2..638234efd698dcb767945447e1faa1c9631e55e8 100644 (file)
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
+#include "gimple.h"
 #include "diagnostic-core.h"   /* For internal_error/fatal_error.  */
 #include "flags.h"
 #include "gfortran.h"
@@ -630,18 +631,27 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
     {
       /* Allocate the temporary.  */
       onstack = !dynamic && initial == NULL_TREE
-                        && gfc_can_put_var_on_stack (size);
+                        && (gfc_option.flag_stack_arrays
+                            || gfc_can_put_var_on_stack (size));
 
       if (onstack)
        {
          /* Make a temporary variable to hold the data.  */
          tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
                                 nelem, gfc_index_one_node);
+         tmp = gfc_evaluate_now (tmp, pre);
          tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
                                  tmp);
          tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
                                  tmp);
          tmp = gfc_create_var (tmp, "A");
+         /* If we're here only because of -fstack-arrays we have to
+            emit a DECL_EXPR to make the gimplifier emit alloca calls.  */
+         if (!gfc_can_put_var_on_stack (size))
+           gfc_add_expr_to_block (pre,
+                                  fold_build1_loc (input_location,
+                                                   DECL_EXPR, TREE_TYPE (tmp),
+                                                   tmp));
          tmp = gfc_build_addr_expr (NULL_TREE, tmp);
          gfc_conv_descriptor_data_set (pre, desc, tmp);
        }
@@ -4759,9 +4769,11 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
 {
   stmtblock_t init;
   tree type;
-  tree tmp;
+  tree tmp = NULL_TREE;
   tree size;
   tree offset;
+  tree space;
+  tree inittree;
   bool onstack;
 
   gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
@@ -4818,15 +4830,30 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
       return;
     }
 
-  /* The size is the number of elements in the array, so multiply by the
-     size of an element to get the total size.  */
-  tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
-  size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                         size, fold_convert (gfc_array_index_type, tmp));
+  if (gfc_option.flag_stack_arrays)
+    {
+      gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
+      space = build_decl (sym->declared_at.lb->location,
+                         VAR_DECL, create_tmp_var_name ("A"),
+                         TREE_TYPE (TREE_TYPE (decl)));
+      gfc_trans_vla_type_sizes (sym, &init);
+    }
+  else
+    {
+      /* The size is the number of elements in the array, so multiply by the
+        size of an element to get the total size.  */
+      tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
+      size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+                             size, fold_convert (gfc_array_index_type, tmp));
 
-  /* Allocate memory to hold the data.  */
-  tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
-  gfc_add_modify (&init, decl, tmp);
+      /* Allocate memory to hold the data.  */
+      tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
+      gfc_add_modify (&init, decl, tmp);
+
+      /* Free the temporary.  */
+      tmp = gfc_call_free (convert (pvoid_type_node, decl));
+      space = NULL_TREE;
+    }
 
   /* Set offset of the array.  */
   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
@@ -4835,10 +4862,26 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
   /* Automatic arrays should not have initializers.  */
   gcc_assert (!sym->value);
 
-  /* Free the temporary.  */
-  tmp = gfc_call_free (convert (pvoid_type_node, decl));
+  inittree = gfc_finish_block (&init);
 
-  gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
+  if (space)
+    {
+      tree addr;
+      pushdecl (space);
+
+      /* Don't create new scope, emit the DECL_EXPR in exactly the scope
+         where also space is located.  */
+      gfc_init_block (&init);
+      tmp = fold_build1_loc (input_location, DECL_EXPR,
+                            TREE_TYPE (space), space);
+      gfc_add_expr_to_block (&init, tmp);
+      addr = fold_build1_loc (sym->declared_at.lb->location,
+                             ADDR_EXPR, TREE_TYPE (decl), space);
+      gfc_add_modify (&init, decl, addr);
+      gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
+      tmp = NULL_TREE;
+    }
+  gfc_add_init_cleanup (block, inittree, tmp);
 }