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?
Tobias
2012-02-14 Tobias Burnus <bur...@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 <bur...@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;
break;
+ 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;
break;
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
+Wrealloc-lhs
+Fortran Warning
+Warn when a left-hand-side array variable is reallocated
+
+Wrealloc-lhs-all
+Fortran Warning
+Warn when a left-hand-side variable is reallocated
+
Wreturn-type
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" }
+end