[Fortran] PR 52196 add -Wrealloc-lhs(-all)

Message ID 4F3A489D.1050905@net-b.de
State New
Headers show

Commit Message

Tobias Burnus Feb. 14, 2012, 11:42 a.m.
Hi all,

in order to gain an overview for our code whether the recent RESHAPE 
(and friends) bug affects us and to determine for which assignment a 
reallocation happens, useful to mitigate performance issues, I added 
-Wrealloc-lhs and -Wrealloc-lhs-all.

The flag -Wrealloc-lhs is the more useful flag: It's about arrays of 
intrinsic types, which are more likely to appear in hot loops than other 
types of reallocatable variables such as derived types or (scalar) 
character  variables with deferred length.

Using it, I also found that there is a rather common class of 
expressions, related to scaling, array addition or complex conjugation, 
where the same array is on the LHS and RHS. In that case, gfortran 
should avoid inserting the reallocation. (Cf. PR 52243.) Fortunately, 
-O0 is often sufficient to remove the reallocation code. In turn, the 
warning might be printed even if at the end no realloc code is generated 
or present with -O1. Nevertheless, it can help to aid optimizing the 
code, though, blindly adding "(:,:)" everywhere doesn't make sense - but 
it also doesn't harm either. (At least for code which doesn't use 
realloc on assignment on purpose ;-)

Build and regtested on x86-64-linux.
OK for the (4.8?) trunk?



Mikael Morin Feb. 27, 2012, 8:59 p.m. | #1

On Tuesday 14 February 2012 12:42:21 Tobias Burnus wrote:
> Fortunately, -O0 is often sufficient to remove the reallocation code. 
I guess you mean -O1 here...

> In turn, the warning might be printed even if at the end no realloc code is
> generated or present with -O1. 
Can it be caused by the frontend not going in the realloc-lhs functions in 
some cases? Especially, it seems that there is a missing codimension/coindexed 
condition guarding the warning if I compare to the flag_realloc_lhs conditions 
in trans-expr.c
I would rather move the warnings to a function and call it in the places where 
we really generate the extra code, like it's done for -Warray-temporaries.



2012-02-14  Tobias Burnus  <burnus@net-b.de>

	PR fortran/52196
	* lang.opt (Wrealloc-lhs, Wrealloc-lhs-all): New flags.
	* gfortran.h (gfc_option_t): Add them.
	* options.c (gfc_init_options, gfc_post_options,
	gfc_handle_option): Handle them.
	* resolve.c (resolve_ordinary_assign): Ditto.
	* invoke.texi: Document them.

2012-02-14  Tobias Burnus  <burnus@net-b.de>

	PR fortran/52196
	* gfortran.dg/realloc_on_assign_13.f90: New.

Index: gcc/fortran/options.c
--- gcc/fortran/options.c	(revision 184200)
+++ gcc/fortran/options.c	(working copy)
@@ -110,6 +110,8 @@  gfc_init_options (unsigned int decoded_options_cou
   gfc_option.warn_align_commons = 1;
   gfc_option.warn_real_q_constant = 0;
   gfc_option.warn_unused_dummy_argument = 0;
+  gfc_option.warn_realloc_lhs = 0;
+  gfc_option.warn_realloc_lhs_all = 0;
   gfc_option.max_errors = 25;
   gfc_option.flag_all_intrinsics = 0;
@@ -436,6 +438,9 @@  gfc_post_options (const char **pfilename)
   if (gfc_option.flag_frontend_optimize == -1)
     gfc_option.flag_frontend_optimize = optimize;
+  if (gfc_option.warn_realloc_lhs_all)
+    gfc_option.warn_realloc_lhs = 1;
   gfc_cpp_post_options ();
 /* FIXME: return gfc_cpp_preprocess_only ();
@@ -648,6 +653,14 @@  gfc_handle_option (size_t scode, const char *arg,
       gfc_option.warn_line_truncation = value;
+    case OPT_Wrealloc_lhs:
+      gfc_option.warn_realloc_lhs = value;
+      break;
+    case OPT_Wrealloc_lhs_all:
+      gfc_option.warn_realloc_lhs_all = value;
+      break;
     case OPT_Wreturn_type:
       warn_return_type = value;
Index: gcc/fortran/gfortran.h
--- gcc/fortran/gfortran.h	(revision 184200)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -2215,6 +2215,8 @@  typedef struct
   int warn_align_commons;
   int warn_real_q_constant;
   int warn_unused_dummy_argument;
+  int warn_realloc_lhs;
+  int warn_realloc_lhs_all;
   int max_errors;
   int flag_all_intrinsics;
Index: gcc/fortran/lang.opt
--- gcc/fortran/lang.opt	(revision 184200)
+++ gcc/fortran/lang.opt	(working copy)
@@ -246,6 +246,14 @@  Wreal-q-constant
 Fortran Warning
 Warn about real-literal-constants with 'q' exponent-letter
+Fortran Warning
+Warn when a left-hand-side array variable is reallocated
+Fortran Warning
+Warn when a left-hand-side variable is reallocated
 Fortran Warning
 ; Documented in C
Index: gcc/fortran/invoke.texi
--- gcc/fortran/invoke.texi	(revision 184200)
+++ gcc/fortran/invoke.texi	(working copy)
@@ -146,9 +146,8 @@  and warnings}.
 -Wconversion -Wfunction-elimination -Wimplicit-interface @gol
 -Wimplicit-procedure -Wintrinsic-shadow -Wintrinsics-std @gol
 -Wline-truncation -Wno-align-commons -Wno-tabs -Wreal-q-constant @gol
--Wsurprising -Wunderflow -Wunused-parameter -fmax-errors=@var{n}
--fsyntax-only @gol
--pedantic -pedantic-errors
+-Wsurprising -Wunderflow -Wunused-parameter -Wrealloc-lhs Wrealloc-lhs-all @gol
+-fmax-errors=@var{n} -fsyntax-only -pedantic -pedantic-errors
 @item Debugging Options
@@ -911,7 +910,24 @@  off via @option{-Wno-align-commons}. See also @opt
 Warn if any calls to functions are eliminated by the optimizations
 enabled by the @option{-ffrontend-optimize} option.
+@item -Wrealloc-lhs
+@opindex @code{Wrealloc-lhs}
+@cindex Reallocate the LHS in assignments, notification
+Warn when the compiler might insert code to for allocation or reallocation of
+an allocatable array variable of intrinsic type in intrinsic assignments.  In
+hot loops, the Fortran 2003 reallocation feature may reduce the performance.
+If the array is already allocated with the correct shape, consider using a
+whole-array array-spec (e.g. @code{(:,:,:)}) for the variable on the left-hand
+side to prevent the reallocation check. Note that in some cases the warning
+is shown, even if the compiler will optimize reallocation checks away.  For
+instance, when the right-hand side contains the same variable multiplied by
+a scalar.  See also @option{-frealloc-lhs}.
+@item -Wrealloc-lhs-all
+@opindex @code{Wrealloc-lhs-all}
+Warn when the compiler inserts code to for allocation or reallocation of an
+allocatable variable; this includes scalars and derived types.
 @item -Werror
 @opindex @code{Werror}
 @cindex warnings, to errors
@@ -1553,7 +1569,8 @@  need to be in effect. The parentheses protection i
 @cindex Reallocate the LHS in assignments
 An allocatable left-hand side of an intrinsic assignment is automatically
 (re)allocated if it is either unallocated or has a different shape. The
-option is enabled by default except when @option{-std=f95} is given.
+option is enabled by default except when @option{-std=f95} is given. See
+also @option{-Wrealloc-lhs}.
 @item -faggressive-function-elimination
 @opindex @code{faggressive-function-elimination}
Index: gcc/fortran/resolve.c
--- gcc/fortran/resolve.c	(revision 184200)
+++ gcc/fortran/resolve.c	(working copy)
@@ -9237,6 +9237,20 @@  resolve_ordinary_assign (gfc_code *code, gfc_names
   gfc_check_assign (lhs, rhs, 1);
+  if (gfc_option.flag_realloc_lhs && gfc_expr_attr (lhs).allocatable)
+    {
+      if (lhs->rank && lhs->ts.type != BT_CLASS && lhs->ts.type != BT_DERIVED
+	  && rhs->rank && gfc_option.warn_realloc_lhs)
+	gfc_warning ("Code for reallocating the allocatable array at %L might "
+		     "be added", &lhs->where);
+      else if (gfc_option.warn_realloc_lhs_all && (lhs->rank == 0 || rhs->rank))
+	gfc_warning ("Code for reallocating the allocatable variable at %L "
+		     "might be added", &lhs->where);
+    }
   return false;
Index: gcc/testsuite/gfortran.dg/realloc_on_assign_13.f90
--- gcc/testsuite/gfortran.dg/realloc_on_assign_13.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/realloc_on_assign_13.f90	(working copy)
@@ -0,0 +1,16 @@ 
+! { dg-do compile }
+! { dg-options "-Wrealloc-lhs-all -Wrealloc-lhs" }
+! PR fortran/52196
+type t
+  integer :: x
+end type t
+integer, allocatable :: a(:), b
+type(t), allocatable :: c(:)
+allocate(a(2), b, c(1))
+b = 4      ! { dg-warning "Code for reallocating the allocatable variable" }
+a = [b,b]  ! { dg-warning "Code for reallocating the allocatable array" }
+c = [t(4)] ! { dg-warning "Code for reallocating the allocatable variable" }