Hello world,

the attached patch introduces a new option, -finline-pack.

Since the fix for PR88821, we now do inline packing of
arguments (if required) via the scalarizer, instead of
using _gfortran_internal_[un]pack when optimizing, but
not when optimizing for size.

This introduces (really) large performance gains for some test
cases because now the middle end can see through the packing.
On the other hand, for test cases which do a _lot_ of this,
compile time and code size can increase by quite a bit.

So, this patch introduces an option to control that behavior,
so that people can turn it off on a by-file basis if they
don't want it.

OK for trunk?

Regards

        Thomas

Introduce -finline-pack.

2019-12-07  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR middle-end/91512
        PR fortran/92738
        * invoke.texi: Document -finline-pack.
        * lang.opt: Add -finline-pack.
        * options.c (gfc_post_options): Handle -finline-pack.
        * trans-array.c (gfc_conv_array_parameter): Use flag_inline_pack
        instead of checking for optimize and optimize_size.

2019-12-07  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR middle-end/91512
        PR fortran/92738
        * gfortran.dg/inline_pack_25.f90: New test.
Index: invoke.texi
===================================================================
--- invoke.texi	(Revision 279064)
+++ invoke.texi	(Arbeitskopie)
@@ -192,8 +192,9 @@ and warnings}.
 -ffrontend-loop-interchange -ffrontend-optimize @gol
 -finit-character=@var{n} -finit-integer=@var{n} -finit-local-zero @gol
 -finit-derived -finit-logical=@var{<true|false>} @gol
--finit-real=@var{<zero|inf|-inf|nan|snan>} @gol
--finline-matmul-limit=@var{n} -fmax-array-constructor=@var{n} @gol
+-finit-real=@var{<zero|inf|-inf|nan|snan>}
+-finline-matmul-limit=@var{n} @gol
+-finline-pack -fmax-array-constructor=@var{n} @gol
 -fmax-stack-var-size=@var{n} -fno-align-commons -fno-automatic @gol
 -fno-protect-parens -fno-underscoring -fsecond-underscore @gol
 -fpack-derived -frealloc-lhs -frecursive -frepack-arrays @gol
@@ -1779,6 +1780,34 @@ compiled with the @option{-fshort-enums} option.
 GNU Fortran choose the smallest @code{INTEGER} kind a given
 enumerator set will fit in, and give all its enumerators this kind.
 
+@item -finline-pack
+@opindex @code{finline-pack}
+When passing an assumed-shape argument of a procedure as actual
+argument to an assumed-size or explicit size or as argument to a
+procedure that does not have an explicit interface, the argument may
+have to be packed, that is put into contiguous memory. An example is
+the call to @code{foo} in
+@smallexample
+  subroutine foo(a)
+     real, dimension(*) :: a
+  end subroutine foo
+  subroutine bar(b)
+     real, dimension(:) :: b
+     call foo(b)
+  end subroutine bar
+@end smallexample
+
+When @option{-finline-pack} is in effect, this packing will be
+performed by inline code. This allows for more optimization while
+increasing code size.
+
+@option{-finlie-pack} is implied by any of the @option{-O} options
+except when optimizing for size via @option{-Os}.  If the code
+contains a very large number of argument that have to be packed, code
+size and also compilation time may become excessive.  If that is the
+case, it may be better to disable this option.  Instances of packing
+can be found by using by using @option{-Warray-temporaries}.
+
 @item -fexternal-blas
 @opindex @code{fexternal-blas}
 This option will make @command{gfortran} generate calls to BLAS functions
Index: lang.opt
===================================================================
--- lang.opt	(Revision 279064)
+++ lang.opt	(Arbeitskopie)
@@ -647,6 +647,10 @@ Enum(gfc_init_local_real) String(inf) Value(GFC_IN
 EnumValue
 Enum(gfc_init_local_real) String(-inf) Value(GFC_INIT_REAL_NEG_INF)
 
+finline-pack
+Fortran  Var(flag_inline_pack) Init(-1)
+-finline-pack	Perform argument packing inline
+
 finline-matmul-limit=
 Fortran RejectNegative Joined UInteger Var(flag_inline_matmul_limit) Init(-1)
 -finline-matmul-limit=<n>	Specify the size of the largest matrix for which matmul will be inlined.
Index: options.c
===================================================================
--- options.c	(Revision 279064)
+++ options.c	(Arbeitskopie)
@@ -467,6 +467,11 @@ gfc_post_options (const char **pfilename)
   if (flag_frontend_loop_interchange == -1)
     flag_frontend_loop_interchange = optimize;
 
+  /* Do inline packing by default if optimizing, but not if
+     optimizing for size.  */
+  if (flag_inline_pack == -1)
+    flag_inline_pack = optimize && !optimize_size;
+
   if (flag_max_array_constructor < 65535)
     flag_max_array_constructor = 65535;
 
Index: trans-array.c
===================================================================
--- trans-array.c	(Revision 279064)
+++ trans-array.c	(Arbeitskopie)
@@ -8139,7 +8139,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr *
 	 making the packing and unpacking operation visible to the
 	 optimizers.  */
 
-      if (g77 && optimize && !optimize_size && expr->expr_type == EXPR_VARIABLE
+      if (g77 && flag_inline_pack && expr->expr_type == EXPR_VARIABLE
 	  && !is_pointer (expr) && ! gfc_has_dimen_vector_ref (expr)
 	  && (fsym == NULL || fsym->ts.type != BT_ASSUMED))
 	{
! { dg-do compile }
! { dg-options "-fno-inline-pack -O -fdump-tree-original" }
! PR fortran/92738, middle-end/91512
! Check that -fno-inline-pack does indeed suppress inline packing.
module x
  implicit none
contains
  subroutine foo(x)
    real, dimension(:), intent(inout) :: x
    call bar (x, size(x))
  end subroutine foo
  subroutine bar (x, n)
    integer, intent(in) :: n
    real, dimension(n) :: x
    x = -x
  end subroutine bar
end module x
! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_internal_unpack" 1 "original" } }

Reply via email to