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]

Infamous PR fortran/19925


Well, I spent some time last week thinking about PR
fortran/19925 and have decided that the best option
may be to punt.  Consider the somewhat far fetched 
but legal Fortran, 

   program test
     implicit none
     integer j
     integer, parameter :: n = 1000000
     integer, parameter :: i(n) = (/ (2*j, j = 1, n) /)
     real :: x(i(5))
     do j = 1, i(5)
        x(j) =  sin(i(j) * 1.23)
     end do
     print *, x
   end program test

Most possible solutions that I could fathom would inhibit
the optimizer from possibly optimizing the above loop.  

So, I've come up with the following patch.  It does not
fix the compile time problem, the memory consumption 
problem during compilation, nor the size of an object file.
It simply gives a user a method (or more appropriately a
gun) to shoot their feet if they do something like the above.
The above code will not compile with gfortran.  With my 
patch, one can do

gfortran -fmax-array-construct=1000000 test.f90

If the gfortran maintainers prefer a better solution, then I'll
certainly won't be offended.

2008-09-13  Steven G. Kargl  <kargls@comcast.net>

	PR fortran/19925
	* trans-array.c (gfc_trans_array_constructor_value): Replace an
	internal_error with gfc_error_now.
	* array.c: Remove GFC_MAX_AC_EXPAND
	(gfc_expand_constructor): Use gfc_option.flag_max_array_constructor.
	* gfortran.h: Add flag_max_array_constructor
	* lang.opt: Add -fmax-array-constructor option.
	* invoke.texi: Document option.
	* options.c (gfc_init_options): Set
	gfc_option.flag_max_array_constructor
	(gfc_handle_option): Process option.


-- 
Steve
Index: trans-array.c
===================================================================
--- trans-array.c	(revision 140346)
+++ trans-array.c	(working copy)
@@ -1246,7 +1246,7 @@ gfc_trans_array_constructor_value (stmtb
             }
 	}
 
-      /* The frontend should already have done any expansions possible
+      /* The frontend should already have done any expansions /
 	 at compile-time.  */
       if (!c->iterator)
 	{
@@ -3899,9 +3899,10 @@ gfc_conv_array_initializer (tree type, g
             {
               /* Problems occur when we get something like
                  integer :: a(lots) = (/(i, i=1,lots)/)  */
-              /* TODO: Unexpanded array initializers.  */
-              internal_error
-                ("Possible frontend bug: array constructor not expanded");
+              gfc_error_now ("Array constructor expansion requires increase "
+			     "in upper limit.  See -fmax-array-constructor " 
+			     "option");
+	      return NULL_TREE;
 	    }
           if (mpz_cmp_si (c->n.offset, 0) != 0)
             index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
Index: array.c
===================================================================
--- array.c	(revision 140346)
+++ array.c	(working copy)
@@ -24,13 +24,6 @@ along with GCC; see the file COPYING3.  
 #include "gfortran.h"
 #include "match.h"
 
-/* This parameter is the size of the largest array constructor that we
-   will expand to an array constructor without iterators.
-   Constructors larger than this will remain in the iterator form.  */
-
-#define GFC_MAX_AC_EXPAND 65535
-
-
 /**************** Array reference matching subroutines *****************/
 
 /* Copy an array reference structure.  */
@@ -1463,7 +1456,7 @@ gfc_expand_constructor (gfc_expr *e)
   gfc_expr *f;
   gfc_try rc;
 
-  f = gfc_get_array_element (e, GFC_MAX_AC_EXPAND);
+  f = gfc_get_array_element (e, gfc_option.flag_max_array_constructor);
   if (f != NULL)
     {
       gfc_free_expr (f);
Index: gfortran.h
===================================================================
--- gfortran.h	(revision 140346)
+++ gfortran.h	(working copy)
@@ -1980,6 +1980,7 @@ typedef struct
   int flag_second_underscore;
   int flag_implicit_none;
   int flag_max_stack_var_size;
+  int flag_max_array_constructor;
   int flag_range_check;
   int flag_pack_derived;
   int flag_repack_arrays;
Index: lang.opt
===================================================================
--- lang.opt	(revision 140346)
+++ lang.opt	(working copy)
@@ -276,6 +276,10 @@ finit-real=
 Fortran RejectNegative Joined
 -finit-real=<zero|nan|inf|-inf> Initialize local real variables
 
+fmax-array-constructor=
+Fortran RejectNegative Joined UInteger
+-fmax-array-constructor=<n>        Maximum number of objects in an array constructor
+
 fmax-errors=
 Fortran RejectNegative Joined UInteger
 -fmax-errors=<n>	Maximum number of errors to report
Index: invoke.texi
===================================================================
--- invoke.texi	(revision 140346)
+++ invoke.texi	(working copy)
@@ -147,7 +147,8 @@ and warnings}.
 
 @item Directory Options
 @xref{Directory Options,,Options for directory search}.
-@gccoptlist{-I@var{dir}  -J@var{dir}  -M@var{dir}  -fintrinsic-modules-path @var{dir}}
+@gccoptlist{-I@var{dir}  -J@var{dir}  -M@var{dir}  @gol
+-fintrinsic-modules-path @var{dir}}
 
 @item Link Options
 @xref{Link Options,,Options for influencing the linking step}.
@@ -161,9 +162,10 @@ and warnings}.
 
 @item Code Generation Options
 @xref{Code Gen Options,,Options for code generation conventions}.
-@gccoptlist{-fno-automatic  -ff2c  -fno-underscoring
+@gccoptlist{-fno-automatic  -ff2c  -fno-underscoring @gol
 -fsecond-underscore @gol
--fbounds-check -fcheck-array-temporaries  -fmax-stack-var-size=@var{n} @gol
+-fbounds-check -fcheck-array-temporaries  -fmax-array-constructor =@var{n} @gol
+-fmax-stack-var-size=@var{n} @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>} @gol
@@ -1182,6 +1184,28 @@ sometimes useful in optimization, in ord
 Note: The warning is only printed once per location.
 
 
+@item -fmax-array-constructor=@var{n}
+@opindex @code{fmax-array-constructor}
+This option can be used to increase the upper limit permitted in 
+array constructors.  The code below requires this option to expand
+the array at compile time.
+
+@smallexample
+@code{program test}
+@code{implicit none}
+@code{integer j}
+@code{integer, parameter :: n = 100000}
+@code{integer, parameter :: i(n) = (/ (2*j, j = 1, n) /)}
+@code{print '(10(I0,1X))', i}
+@code{end program test}
+@end smallexample
+
+@emph{Caution:  This option can lead to long compile times and excessively
+large object files.}
+
+The default value for @var{n} is 65535.
+
+
 @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
Index: options.c
===================================================================
--- options.c	(revision 140346)
+++ options.c	(working copy)
@@ -62,6 +62,7 @@ gfc_init_options (unsigned int argc, con
   gfc_option.max_continue_free = 255;
   gfc_option.max_identifier_length = GFC_MAX_SYMBOL_LEN;
   gfc_option.max_subrecord_length = 0;
+  gfc_option.flag_max_array_constructor = 65535;
   gfc_option.convert = GFC_CONVERT_NATIVE;
   gfc_option.record_marker = 0;
   gfc_option.dump_parse_tree = 0;
@@ -633,6 +634,10 @@ gfc_handle_option (size_t scode, const c
       gfc_add_intrinsic_modules_path (arg);
       break;
 
+    case OPT_fmax_array_constructor_:
+      gfc_option.flag_max_array_constructor = value > 65535 ? value : 65535;
+      break;
+
     case OPT_fmax_errors_:
       gfc_option.max_errors = value;
       break;

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