This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, Fortran] Add -frecursive, imply it with -fopenmp, check for flag conflicts and update invoke.texi


:ADDPATCH fortran:

This patch supercedes the patch by Asher,
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00960.html
and by me
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00996.html

By default, gfortran currently puts local variables (with known bounds),
which are smaller than 32kbits, on the  stack, variables which are
bigger are marked as static. (And automatic variables etc. are allocated
on the heap.)

Some legacy applications imply SAVE without actually specifying it; in
this case -fno-automatic (or -fmax-stack-var-size=0) has to be used.

Other legacy applications call procedures recursively without using the
RECURSIVE attribute - or the recursion happens through the backdoor via
parallelization (OpenMP, but potentially also shared-memory MPI, Posix
Threads, ...). In this case the local variables of such procedures shall
not be in static memory.

Internally, gfortran uses gfc_option.flag_max_stack_var_size = -1 for
the latter, but since "fmax-stack-var-size=" is "UInteger" thus -1
cannot be set from the command line.

This patch introduces the option -frecursive to disable static memory
for local variables; makes -fopenmp imply -frecursive and adds a couple
of warning if conflicting options have been specified. The hierarchy of
the options is:

1. Implied: stack-var-size = 32 k (implied by the default
-fmax-stack-var-size= 32k and -fautomatic)
2. -fopenmp implies: stack-var-size=-1
3. Explicitly set -fmax-stack-var-size=<n>
4. -frecursive: stack-var-size=-1
5. -fno-automatic: stack-var-size=0

Regression tested on x86_64-unknown-linux-gnu and with "make info" and
"make pdf".
Ok for the trunk?

Tobias
2007-08-20  Asher Langton  <langton2@llnl.gov>
	    Tobias Burnus  <burnus@net-b.de>

        * gfortran.h (gfc_option_t): Add flag_recursive.
	* lang.opt: Add -frecursive option and update -fopenmp.
	* invoke.texi (-frecursive): Document new option.
	(-fopenmp,-fno-automatic,-fmax-stack-var-size): Update.
	* options.c (gfc_init_options, gfc_post_options,
	gfc_handle_option): Add -frecursive and modify -fopenmp.
	(gfc_post_options): Add warning for conflicting flags.

2007-08-20  Asher Langton  <langton2@llnl.gov>

	* gfortran.dg/recursive_stack.f90: New.
	* gfortran.dg/openmp_stack.f90: New.

Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(Revision 127641)
+++ gcc/fortran/gfortran.h	(Arbeitskopie)
@@ -1863,6 +1866,7 @@ typedef struct
   int flag_openmp;
   int flag_sign_zero;
   int flag_module_private;
+  int flag_recursive;
 
   int fpe;
 
Index: gcc/fortran/lang.opt
===================================================================
--- gcc/fortran/lang.opt	(Revision 127641)
+++ gcc/fortran/lang.opt	(Arbeitskopie)
@@ -218,7 +218,7 @@ Set default accessibility of module enti
 
 fopenmp
 Fortran
-Enable OpenMP
+Enable OpenMP (also sets frecursive)
 
 fpack-derived
 Fortran
@@ -240,6 +240,10 @@ frecord-marker=8
 Fortran RejectNegative
 Use an 8-byte record marker for unformatted files
 
+frecursive
+Fortran
+Allocate local variables on the stack to allow indirect recursion
+
 frepack-arrays
 Fortran
 Copy array sections into a contiguous block on procedure entry
Index: gcc/fortran/options.c
===================================================================
--- gcc/fortran/options.c	(Revision 127641)
+++ gcc/fortran/options.c	(Arbeitskopie)
@@ -86,7 +86,10 @@ gfc_init_options (unsigned int argc ATTR
   gfc_option.flag_f2c = 0;
   gfc_option.flag_second_underscore = -1;
   gfc_option.flag_implicit_none = 0;
-  gfc_option.flag_max_stack_var_size = 32768;
+
+  /* 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_range_check = 1;
   gfc_option.flag_pack_derived = 0;
   gfc_option.flag_repack_arrays = 0;
@@ -103,6 +106,7 @@ gfc_init_options (unsigned int argc ATTR
   gfc_option.flag_d_lines = -1;
   gfc_option.flag_openmp = 0;
   gfc_option.flag_sign_zero = 1;
+  gfc_option.flag_recursive = 0;
 
   gfc_option.fpe = 0;
 
@@ -290,6 +294,37 @@ gfc_post_options (const char **pfilename
   if (gfc_option.flag_second_underscore == -1)
     gfc_option.flag_second_underscore = gfc_option.flag_f2c;
 
+  if (!gfc_option.flag_automatic && gfc_option.flag_max_stack_var_size != -2
+      && gfc_option.flag_max_stack_var_size != 0)
+    gfc_warning_now ("Flag -fno-automatic overwrites -fmax-stack-var-size=%d",
+		     gfc_option.flag_max_stack_var_size);
+  else if (!gfc_option.flag_automatic && gfc_option.flag_recursive)
+    gfc_warning_now ("Flag -fno-automatic overwrites -frecursive");
+  else if (!gfc_option.flag_automatic && gfc_option.flag_openmp)
+    gfc_warning_now ("Flag -fno-automatic overwrites -frecursive implied by "
+		     "-fopenmp");
+  else if (gfc_option.flag_max_stack_var_size != -2
+	   && gfc_option.flag_recursive)
+    gfc_warning_now ("Flag -frecursive overwrites -fmax-stack-var-size=%d",
+		     gfc_option.flag_max_stack_var_size);
+  else if (gfc_option.flag_max_stack_var_size != -2
+	   && gfc_option.flag_openmp)
+    gfc_warning_now ("Flag -fmax-stack-var-size=%d overwrites -frecursive "
+		     "implied by -fopenmp", 
+		     gfc_option.flag_max_stack_var_size);
+
+  /* Implied -frecursive; implemented as -fmax-stack-var-size=-1.  */
+  if (gfc_option.flag_max_stack_var_size == -2 && gfc_option.flag_openmp)
+    gfc_option.flag_max_stack_var_size = -1;
+
+  /* Set default.  */
+  if (gfc_option.flag_max_stack_var_size == -2)
+    gfc_option.flag_max_stack_var_size = 32768;
+
+  /* Implement -frecursive as -fmax-stack-var-size=-1.  */
+  if (gfc_option.flag_recursive)
+    gfc_option.flag_max_stack_var_size = -1;
+
   /* Implement -fno-automatic as -fmax-stack-var-size=0.  */
   if (!gfc_option.flag_automatic)
     gfc_option.flag_max_stack_var_size = 0;
@@ -698,6 +733,11 @@ gfc_handle_option (size_t scode, const c
 			 MAX_SUBRECORD_LENGTH);
 
       gfc_option.max_subrecord_length = value;
+      break;
+
+    case OPT_frecursive:
+      gfc_option.flag_recursive = 1;
+      break;
     }
 
   return result;
Index: gcc/fortran/invoke.texi
===================================================================
--- gcc/fortran/invoke.texi	(Revision 127641)
+++ gcc/fortran/invoke.texi	(Arbeitskopie)
@@ -156,7 +156,7 @@ and warnings}.
 -fsecond-underscore @gol
 -fbounds-check  -fmax-stack-var-size=@var{n} @gol
 -fpack-derived  -frepack-arrays  -fshort-enums  -fexternal-blas @gol
--fblas-matmul-limit=@var{n}}
+-fblas-matmul-limit=@var{n} -frecursive}
 @end table
 
 @menu
@@ -296,7 +296,7 @@ and @code{c$omp}, @code{*$omp} and @code
 @code{!$} conditional compilation sentinels in free form
 and @code{c$}, @code{*$} and @code{!$} sentinels in fixed form, 
 and when linking arranges for the OpenMP runtime library to be linked
-in.
+in.  The option @option{-fopenmp} implies @option{-frecursive}.
 
 @item -frange-check
 @opindex @code{frange-check}
@@ -710,10 +710,13 @@ it.
 @opindex @code{fno-automatic}
 @cindex @code{SAVE} statement
 @cindex statement, @code{SAVE}
-Treat each program unit as if the @code{SAVE} statement was specified for
-every local variable and array referenced in it. Does not affect common
-blocks. (Some Fortran compilers provide this option under the name
-@option{-static}.)
+Treat each program unit (except those marked as RECURSIVE) as if the
+@code{SAVE} statement were specified for every local variable and array
+referenced in it. Does not affect common blocks. (Some Fortran compilers
+provide this option under the name @option{-static} or @option{-save}.)
+The default is @option{-fautomatic} which uses the stack for local
+variables smaller than the value given by @option{-fmax-stack-var-size}.
+Use the option @option{-frecursive} to use no static memory. 
 
 @item -ff2c
 @opindex ff2c
@@ -865,7 +868,10 @@ substring references.
 @item -fmax-stack-var-size=@var{n}
 @opindex @code{fmax-stack-var-size}
 This option specifies the size in bytes of the largest array that will be put
-on the stack.
+on the stack; if the size is exceeded static memory is used (except in
+procedures marked as RECURSIVE). Use the option @option{-frecursive} to
+allow for recursive procedures which do not have a RECURSIVE attribute or
+for parallel programs. And use @option{-fno-automatic} to use never the stack.
 
 This option currently only affects local arrays declared with constant
 bounds, and may not apply to all character variables.
@@ -919,6 +925,12 @@ geometric mean of the dimensions of the 
 
 The default value for @var{n} is 30.
 
+@item -frecursive
+@opindex @code{frecursive}
+Allow indirect recursion by forcing all local arrays to be allocated
+on the stack. This flag cannot be use together with
+@option{-fmax-stack-var-size=} or @option{-fno-automatic}.
+
 @end table
 
 @xref{Code Gen Options,,Options for Code Generation Conventions,
Index: gcc/testsuite/gfortran.dg/openmp_stack.f90
===================================================================
--- gcc/testsuite/gfortran.dg/openmp_stack.f90	(Revision 0)
+++ gcc/testsuite/gfortran.dg/openmp_stack.f90	(Revision 0)
@@ -0,0 +1,22 @@
+! { dg-do run}
+! { dg-options "-fopenmp" }
+program openmp_stack
+  implicit none
+  integer id
+  integer ilocs(2)
+  integer omp_get_thread_num, foo
+  call omp_set_num_threads (2)
+!$omp parallel private (id)
+  id = omp_get_thread_num() + 1
+  ilocs(id) = foo()
+!$omp end parallel
+  ! Check that the two threads are not sharing a location for
+  ! the array x in foo()
+  if (ilocs(1) .eq. ilocs(2)) call abort
+end program openmp_stack
+
+integer function foo ()
+  implicit none
+  real x(100,100)
+  foo = loc(x)
+end function foo
Index: gcc/testsuite/gfortran.dg/recursive_stack.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_stack.f90	(Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_stack.f90	(Revision 0)
@@ -0,0 +1,21 @@
+! { dg-do run}
+! { dg-options "-frecursive" }
+program recursive_stack
+  call foo (.true.)
+end program recursive_stack
+
+subroutine foo (recurse)
+  logical recurse
+  integer iarray(100,100)
+  if (recurse) then
+     iarray(49,49) = 17
+     call bar
+     if (iarray(49,49) .ne. 17) call abort
+  else
+     iarray(49,49) = 21
+  end if
+end subroutine foo
+
+subroutine bar
+  call foo (.false.)
+end subroutine bar

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]