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_notify@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 <jb@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-ar... 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-ar... 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-ar...
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-ar... --fail curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-ar... --fail curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-ar... --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/c...
Artifacts: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-ar... Build log: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-ar...
Full commit (up to 1000 lines):
<cut> commit d74a8b0579edd0c42921eccc45ab986d24f2fef0 Author: Janne Blomqvist <jb@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 jb@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 jb@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 jb@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 law@redhat.com Mark Eggleston mark.eggleston@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 rguenther@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),
gfc_add_expr_to_block (&block, tmp);errorfunc), nargs + 2, argarray);
@@ -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,
va_end (ap); return result;where, msgid, ap);
} @@ -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)),
gfc_add_expr_to_block (&block2, tmp); }build_empty_stmt (input_location));
@@ -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
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, null_result,("Allocation would exceed memory limit"));
build_call_expr_loc (input_location,
gfor_fndecl_os_error, 1, msg),
trans_os_error_at (NULL,
"Error reallocating to %lu bytes",
fold_convert
gfc_add_expr_to_block (block, tmp);(long_unsigned_type_node, size)), build_empty_stmt (input_location));
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 jb@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 jb@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@lists.linaro.org