I’m running historical performance experiments, and this commit from 2019 
showed up on my radar.  Just in case someone is interested in running Fortran 
code on memory-constrained M-profile cores ...

It appears that Janne’s patch increases code-size of 437.leslie3d by around 2% 
on 32-bit ARM (well, Thumb2, to be precise).  It may be interesting to check 
what’s going on, since AArch64 is not affected.

One possibility is that before this patch all literal-pool entries for error 
messages were shared, and with variation of error messages all of them became 
different entries, thus increasing code size.

--
Maxim Kuvyrkov
https://www.linaro.org

> On 28 Jun 2021, at 00:54, ci_not...@linaro.org wrote:
> 
> Successfully identified regression in *gcc* in CI configuration 
> tcwg_bmk_gnu_tk1/gnu-release-arm-spec2k6-Os_LTO.  So far, this commit has 
> regressed CI configurations:
> - tcwg_bmk_gnu_tk1/gnu-release-arm-spec2k6-Os_LTO
> - tcwg_bmk_tk1/gnu-release-arm-spec2k6-Os
> 
> Culprit:
> <cut>
> commit d74a8b0579edd0c42921eccc45ab986d24f2fef0
> Author: Janne Blomqvist <j...@gcc.gnu.org>
> 
>    PR fortran/68401 Improve allocation error message
> </cut>
> 
> Results regressed to (for first_bad == 
> d74a8b0579edd0c42921eccc45ab986d24f2fef0)
> # reset_artifacts:
> -10
> # build_abe binutils:
> -9
> # build_abe stage1 -- --set gcc_override_configure=--with-mode=thumb --set 
> gcc_override_configure=--disable-libsanitizer:
> -8
> # build_abe linux:
> -7
> # build_abe glibc:
> -6
> # build_abe stage2 -- --set gcc_override_configure=--with-mode=thumb --set 
> gcc_override_configure=--disable-libsanitizer:
> -5
> # true:
> 0
> # benchmark -Os_LTO_mthumb -- 
> artifacts/build-d74a8b0579edd0c42921eccc45ab986d24f2fef0/results_id:
> 1
> # 437.leslie3d,leslie3d_base.default                            regressed by 
> 102
> 
> from (for last_good == 777c02825229f14cf91c6044827ea42a77ded4a3)
> # reset_artifacts:
> -10
> # build_abe binutils:
> -9
> # build_abe stage1 -- --set gcc_override_configure=--with-mode=thumb --set 
> gcc_override_configure=--disable-libsanitizer:
> -8
> # build_abe linux:
> -7
> # build_abe glibc:
> -6
> # build_abe stage2 -- --set gcc_override_configure=--with-mode=thumb --set 
> gcc_override_configure=--disable-libsanitizer:
> -5
> # true:
> 0
> # benchmark -Os_LTO_mthumb -- 
> artifacts/build-777c02825229f14cf91c6044827ea42a77ded4a3/results_id:
> 1
> 
> Artifacts of last_good build: 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/artifact/artifacts/build-777c02825229f14cf91c6044827ea42a77ded4a3/
> Results ID of last_good: 
> tk1_32/tcwg_bmk_gnu_tk1/bisect-gnu-release-arm-spec2k6-Os_LTO/531
> Artifacts of first_bad build: 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/artifact/artifacts/build-d74a8b0579edd0c42921eccc45ab986d24f2fef0/
> Results ID of first_bad: 
> tk1_32/tcwg_bmk_gnu_tk1/bisect-gnu-release-arm-spec2k6-Os_LTO/539
> Build top page/logs: 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/
> 
> Configuration details:
> 
> 
> Reproduce builds:
> <cut>
> mkdir investigate-gcc-d74a8b0579edd0c42921eccc45ab986d24f2fef0
> cd investigate-gcc-d74a8b0579edd0c42921eccc45ab986d24f2fef0
> 
> git clone https://git.linaro.org/toolchain/jenkins-scripts
> 
> mkdir -p artifacts/manifests
> curl -o artifacts/manifests/build-baseline.sh 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/artifact/artifacts/manifests/build-baseline.sh
>  --fail
> curl -o artifacts/manifests/build-parameters.sh 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/artifact/artifacts/manifests/build-parameters.sh
>  --fail
> curl -o artifacts/test.sh 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/artifact/artifacts/test.sh
>  --fail
> chmod +x artifacts/test.sh
> 
> # Reproduce the baseline build (build all pre-requisites)
> ./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh
> 
> cd gcc
> 
> # Reproduce first_bad build
> git checkout --detach d74a8b0579edd0c42921eccc45ab986d24f2fef0
> ../artifacts/test.sh
> 
> # Reproduce last_good build
> git checkout --detach 777c02825229f14cf91c6044827ea42a77ded4a3
> ../artifacts/test.sh
> 
> cd ..
> </cut>
> 
> History of pending regressions and results: 
> https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/ci/tcwg_bmk_gnu_tk1/gnu-release-arm-spec2k6-Os_LTO
> 
> Artifacts: 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/artifact/artifacts/
> Build log: 
> https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-arm-spec2k6-Os_LTO/31/consoleText
> 
> Full commit (up to 1000 lines):
> <cut>
> commit d74a8b0579edd0c42921eccc45ab986d24f2fef0
> Author: Janne Blomqvist <j...@gcc.gnu.org>
> Date:   Sat Aug 17 08:45:37 2019 +0300
> 
>    PR fortran/68401 Improve allocation error message
> 
>    Improve the error message that is printed when a memory allocation
>    fails, by including the location, and the size of the allocation that
>    failed.
> 
>    Regtested on x86_64-pc-linux-gnu.
> 
>    gcc/fortran/ChangeLog:
> 
>    2019-08-17  Janne Blomqvist  <j...@gcc.gnu.org>
> 
>            PR fortran/68401
>            * trans-decl.c (gfc_build_builtin_function_decls): Replace
>            os_error with os_error_at decl.
>            * trans.c (trans_runtime_error_vararg): Modify so the error
>            function decl is passed directly.
>            (gfc_trans_runtime_error): Pass correct error function decl.
>            (gfc_trans_runtime_check): Likewise.
>            (trans_os_error_at): New function.
>            (gfc_call_malloc): Use trans_os_error_at.
>            (gfc_allocate_using_malloc): Likewise.
>            (gfc_call_realloc): Likewise.
>            * trans.h (gfor_fndecl_os_error): Replace with 
> gfor_fndecl_os_error_at.
> 
>    libgfortran/ChangeLog:
> 
>    2019-08-17  Janne Blomqvist  <j...@gcc.gnu.org>
> 
>            PR fortran/68401
>            * gfortran.map: Add GFORTRAN_10 node, add _gfortran_os_error_at
>            symbol.
>            * libgfortran.h (os_error_at): New prototype.
>            * runtime/error.c (os_error_at): New function.
> 
>    From-SVN: r274599
> ---
> gcc/fortran/ChangeLog       | 17 +++++++++++-
> gcc/fortran/trans-decl.c    | 12 ++++----
> gcc/fortran/trans.c         | 68 +++++++++++++++++++++++++++------------------
> gcc/fortran/trans.h         |  2 +-
> libgfortran/ChangeLog       |  8 ++++++
> libgfortran/gfortran.map    |  5 ++++
> libgfortran/libgfortran.h   |  4 +++
> libgfortran/runtime/error.c | 46 +++++++++++++++++++++++++++++-
> 8 files changed, 126 insertions(+), 36 deletions(-)
> 
> diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
> index bab69f3000e..a3b9e6bf486 100644
> --- a/gcc/fortran/ChangeLog
> +++ b/gcc/fortran/ChangeLog
> @@ -1,3 +1,18 @@
> +2019-08-17  Janne Blomqvist  <j...@gcc.gnu.org>
> +
> +     PR fortran/68401
> +     * trans-decl.c (gfc_build_builtin_function_decls): Replace
> +     os_error with os_error_at decl.
> +     * trans.c (trans_runtime_error_vararg): Modify so the error
> +     function decl is passed directly.
> +     (gfc_trans_runtime_error): Pass correct error function decl.
> +     (gfc_trans_runtime_check): Likewise.
> +     (trans_os_error_at): New function.
> +     (gfc_call_malloc): Use trans_os_error_at.
> +     (gfc_allocate_using_malloc): Likewise.
> +     (gfc_call_realloc): Likewise.
> +     * trans.h (gfor_fndecl_os_error): Replace with gfor_fndecl_os_error_at.
> +
> 2019-08-16  Jeff Law <l...@redhat.com>
>           Mark Eggleston <mark.eggles...@codethink.com>
> 
> @@ -18,7 +33,7 @@
>       * trans-common.c (find_equivalence) : New local variable dummy_symbol,
>       accumulated equivalence attributes from each symbol then check for
>       conflicts.
> -  
> +
> 2019-08-16  Richard Biener  <rguent...@suse.de>
> 
>       * trans-intrinsic.c (gfc_conv_intrinsic_findloc): Initialize
> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> index 2a9b852568a..3c6ab60e9b2 100644
> --- a/gcc/fortran/trans-decl.c
> +++ b/gcc/fortran/trans-decl.c
> @@ -102,7 +102,7 @@ tree gfor_fndecl_error_stop_string;
> tree gfor_fndecl_runtime_error;
> tree gfor_fndecl_runtime_error_at;
> tree gfor_fndecl_runtime_warning_at;
> -tree gfor_fndecl_os_error;
> +tree gfor_fndecl_os_error_at;
> tree gfor_fndecl_generate_error;
> tree gfor_fndecl_set_args;
> tree gfor_fndecl_set_fpe;
> @@ -3679,11 +3679,11 @@ gfc_build_builtin_function_decls (void)
>       void_type_node, 3, pvoid_type_node, integer_type_node,
>       pchar_type_node);
> 
> -  gfor_fndecl_os_error = gfc_build_library_function_decl_with_spec (
> -     get_identifier (PREFIX("os_error")), ".R",
> -     void_type_node, 1, pchar_type_node);
> -  /* The runtime_error function does not return.  */
> -  TREE_THIS_VOLATILE (gfor_fndecl_os_error) = 1;
> +  gfor_fndecl_os_error_at = gfc_build_library_function_decl_with_spec (
> +     get_identifier (PREFIX("os_error_at")), ".RR",
> +     void_type_node, -2, pchar_type_node, pchar_type_node);
> +  /* The os_error_at function does not return.  */
> +  TREE_THIS_VOLATILE (gfor_fndecl_os_error_at) = 1;
> 
>   gfor_fndecl_set_args = gfc_build_library_function_decl (
>       get_identifier (PREFIX("set_args")),
> diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
> index 84511477b39..583f6e3b25b 100644
> --- a/gcc/fortran/trans.c
> +++ b/gcc/fortran/trans.c
> @@ -447,7 +447,7 @@ gfc_build_array_ref (tree base, tree offset, tree decl, 
> tree vptr)
>    arguments and a locus.  */
> 
> static tree
> -trans_runtime_error_vararg (bool error, locus* where, const char* msgid,
> +trans_runtime_error_vararg (tree errorfunc, locus* where, const char* msgid,
>                           va_list ap)
> {
>   stmtblock_t block;
> @@ -501,18 +501,13 @@ trans_runtime_error_vararg (bool error, locus* where, 
> const char* msgid,
>   /* Build the function call to runtime_(warning,error)_at; because of the
>      variable number of arguments, we can't use build_call_expr_loc 
> dinput_location,
>      irectly.  */
> -  if (error)
> -    fntype = TREE_TYPE (gfor_fndecl_runtime_error_at);
> -  else
> -    fntype = TREE_TYPE (gfor_fndecl_runtime_warning_at);
> +  fntype = TREE_TYPE (errorfunc);
> 
>   loc = where ? where->lb->location : input_location;
>   tmp = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
>                                  fold_build1_loc (loc, ADDR_EXPR,
>                                            build_pointer_type (fntype),
> -                                          error
> -                                          ? gfor_fndecl_runtime_error_at
> -                                          : gfor_fndecl_runtime_warning_at),
> +                                          errorfunc),
>                                  nargs + 2, argarray);
>   gfc_add_expr_to_block (&block, tmp);
> 
> @@ -527,7 +522,10 @@ gfc_trans_runtime_error (bool error, locus* where, const 
> char* msgid, ...)
>   tree result;
> 
>   va_start (ap, msgid);
> -  result = trans_runtime_error_vararg (error, where, msgid, ap);
> +  result = trans_runtime_error_vararg (error
> +                                    ? gfor_fndecl_runtime_error_at
> +                                    : gfor_fndecl_runtime_warning_at,
> +                                    where, msgid, ap);
>   va_end (ap);
>   return result;
> }
> @@ -566,8 +564,10 @@ gfc_trans_runtime_check (bool error, bool once, tree 
> cond, stmtblock_t * pblock,
>   /* The code to generate the error.  */
>   va_start (ap, msgid);
>   gfc_add_expr_to_block (&block,
> -                      trans_runtime_error_vararg (error, where,
> -                                                  msgid, ap));
> +                      trans_runtime_error_vararg
> +                      (error ? gfor_fndecl_runtime_error_at
> +                       : gfor_fndecl_runtime_warning_at,
> +                       where, msgid, ap));
>   va_end (ap);
> 
>   if (once)
> @@ -595,13 +595,28 @@ gfc_trans_runtime_check (bool error, bool once, tree 
> cond, stmtblock_t * pblock,
> }
> 
> 
> +static tree
> +trans_os_error_at (locus* where, const char* msgid, ...)
> +{
> +  va_list ap;
> +  tree result;
> +
> +  va_start (ap, msgid);
> +  result = trans_runtime_error_vararg (gfor_fndecl_os_error_at,
> +                                    where, msgid, ap);
> +  va_end (ap);
> +  return result;
> +}
> +
> +
> +
> /* Call malloc to allocate size bytes of memory, with special conditions:
>       + if size == 0, return a malloced area of size 1,
>       + if malloc returns NULL, issue a runtime error.  */
> tree
> gfc_call_malloc (stmtblock_t * block, tree type, tree size)
> {
> -  tree tmp, msg, malloc_result, null_result, res, malloc_tree;
> +  tree tmp, malloc_result, null_result, res, malloc_tree;
>   stmtblock_t block2;
> 
>   /* Create a variable to hold the result.  */
> @@ -626,13 +641,14 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree 
> size)
>       null_result = fold_build2_loc (input_location, EQ_EXPR,
>                                    logical_type_node, res,
>                                    build_int_cst (pvoid_type_node, 0));
> -      msg = gfc_build_addr_expr (pchar_type_node,
> -           gfc_build_localized_cstring_const ("Memory allocation failed"));
>       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
>                            null_result,
> -           build_call_expr_loc (input_location,
> -                                gfor_fndecl_os_error, 1, msg),
> -                                build_empty_stmt (input_location));
> +                          trans_os_error_at (NULL,
> +                                             "Error allocating %lu bytes",
> +                                             fold_convert
> +                                             (long_unsigned_type_node,
> +                                              size)),
> +                          build_empty_stmt (input_location));
>       gfc_add_expr_to_block (&block2, tmp);
>     }
> 
> @@ -701,11 +717,9 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree 
> pointer,
>     }
>   else
>     {
> -      /* Here, os_error already implies PRED_NORETURN.  */
> -      tmp = build_call_expr_loc (input_location, gfor_fndecl_os_error, 1,
> -                 gfc_build_addr_expr (pchar_type_node,
> -                              gfc_build_localized_cstring_const
> -                                 ("Allocation would exceed memory limit")));
> +      /* Here, os_error_at already implies PRED_NORETURN.  */
> +      tree lusize = fold_convert (long_unsigned_type_node, size);
> +      tmp = trans_os_error_at (NULL, "Error allocating %lu bytes", lusize);
>       gfc_add_expr_to_block (&on_error, tmp);
>     }
> 
> @@ -1664,7 +1678,7 @@ internal_realloc (void *mem, size_t size)
> tree
> gfc_call_realloc (stmtblock_t * block, tree mem, tree size)
> {
> -  tree msg, res, nonzero, null_result, tmp;
> +  tree res, nonzero, null_result, tmp;
>   tree type = TREE_TYPE (mem);
> 
>   /* Only evaluate the size once.  */
> @@ -1684,12 +1698,12 @@ gfc_call_realloc (stmtblock_t * block, tree mem, tree 
> size)
>                            build_int_cst (size_type_node, 0));
>   null_result = fold_build2_loc (input_location, TRUTH_AND_EXPR, 
> logical_type_node,
>                                null_result, nonzero);
> -  msg = gfc_build_addr_expr (pchar_type_node, 
> gfc_build_localized_cstring_const
> -                          ("Allocation would exceed memory limit"));
>   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
>                        null_result,
> -                      build_call_expr_loc (input_location,
> -                                           gfor_fndecl_os_error, 1, msg),
> +                      trans_os_error_at (NULL,
> +                                         "Error reallocating to %lu bytes",
> +                                         fold_convert
> +                                         (long_unsigned_type_node, size)),
>                        build_empty_stmt (input_location));
>   gfc_add_expr_to_block (block, tmp);
> 
> diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
> index a3726e84140..8082b414df1 100644
> --- a/gcc/fortran/trans.h
> +++ b/gcc/fortran/trans.h
> @@ -803,7 +803,7 @@ extern GTY(()) tree gfor_fndecl_error_stop_string;
> extern GTY(()) tree gfor_fndecl_runtime_error;
> extern GTY(()) tree gfor_fndecl_runtime_error_at;
> extern GTY(()) tree gfor_fndecl_runtime_warning_at;
> -extern GTY(()) tree gfor_fndecl_os_error;
> +extern GTY(()) tree gfor_fndecl_os_error_at;
> extern GTY(()) tree gfor_fndecl_generate_error;
> extern GTY(()) tree gfor_fndecl_set_fpe;
> extern GTY(()) tree gfor_fndecl_set_options;
> diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
> index 7a11ca29fd3..23a4c579351 100644
> --- a/libgfortran/ChangeLog
> +++ b/libgfortran/ChangeLog
> @@ -1,3 +1,11 @@
> +2019-08-17  Janne Blomqvist  <j...@gcc.gnu.org>
> +
> +     PR fortran/68401
> +     * gfortran.map: Add GFORTRAN_10 node, add _gfortran_os_error_at
> +     symbol.
> +     * libgfortran.h (os_error_at): New prototype.
> +     * runtime/error.c (os_error_at): New function.
> +
> 2019-08-13  Janne Blomqvist  <j...@gcc.gnu.org>
> 
>         PR fortran/91414
> diff --git a/libgfortran/gfortran.map b/libgfortran/gfortran.map
> index 2b2243b4fd4..3601bc24414 100644
> --- a/libgfortran/gfortran.map
> +++ b/libgfortran/gfortran.map
> @@ -1602,3 +1602,8 @@ GFORTRAN_9.2 {
>   _gfortran_mfindloc1_r10;
>   _gfortran_sfindloc1_r10;
> } GFORTRAN_9;
> +
> +GFORTRAN_10 {
> +  global:
> +  _gfortran_os_error_at;
> +} GFORTRAN_9.2;
> diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
> index c0db96f02a8..9f535b12e73 100644
> --- a/libgfortran/libgfortran.h
> +++ b/libgfortran/libgfortran.h
> @@ -728,6 +728,10 @@ internal_proto(gfc_xtoa);
> extern _Noreturn void os_error (const char *);
> iexport_proto(os_error);
> 
> +extern _Noreturn void os_error_at (const char *, const char *, ...)
> +  __attribute__ ((format (gfc_printf, 2, 3)));
> +iexport_proto(os_error_at);
> +
> extern void show_locus (st_parameter_common *);
> internal_proto(show_locus);
> 
> diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
> index 0335a165edc..cbe0642f3f8 100644
> --- a/libgfortran/runtime/error.c
> +++ b/libgfortran/runtime/error.c
> @@ -403,7 +403,51 @@ os_error (const char *message)
>   estr_writev (iov, 5);
>   exit_error (1);
> }
> -iexport(os_error);
> +iexport(os_error); /* TODO, DEPRECATED, ABI: Should not be exported
> +                   anymore when bumping so version.  */
> +
> +
> +/* Improved version of os_error with a printf style format string and
> +   a locus.  */
> +
> +void
> +os_error_at (const char *where, const char *message, ...)
> +{
> +  char errmsg[STRERR_MAXSZ];
> +  char buffer[STRERR_MAXSZ];
> +  struct iovec iov[6];
> +  va_list ap;
> +  recursion_check ();
> +  int written;
> +
> +  iov[0].iov_base = (char*) where;
> +  iov[0].iov_len = strlen (where);
> +
> +  iov[1].iov_base = (char*) ": ";
> +  iov[1].iov_len = strlen (iov[1].iov_base);
> +
> +  va_start (ap, message);
> +  written = vsnprintf (buffer, STRERR_MAXSZ, message, ap);
> +  va_end (ap);
> +  iov[2].iov_base = buffer;
> +  if (written >= 0)
> +    iov[2].iov_len = written;
> +  else
> +    iov[2].iov_len = 0;
> +
> +  iov[3].iov_base = (char*) ": ";
> +  iov[3].iov_len = strlen (iov[3].iov_base);
> +
> +  iov[4].iov_base = gf_strerror (errno, errmsg, STRERR_MAXSZ);
> +  iov[4].iov_len = strlen (iov[4].iov_base);
> +
> +  iov[5].iov_base = (char*) "\n";
> +  iov[5].iov_len = 1;
> +
> +  estr_writev (iov, 6);
> +  exit_error (1);
> +}
> +iexport(os_error_at);
> 
> 
> /* void runtime_error()-- These are errors associated with an
> </cut>

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to