Message ID | CAKnkMGtkEPAZ1_-og8j-TFyh=Lq=MFHpzyQqfbh9ifvXuTNUGg@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | [libgcc/ARM,&,testsuite] Optimize executable size when using softfloat fmul/dmul | expand |
FWIW, the testcases were taken from https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01026.html Previous approach for fixing tying of fmul to fdiv can be seen in https://gcc.gnu.org/ml/gcc-patches/2015-04/msg01971.html. As mentioned in the cover letter, this patch went for a completely different approach and does not share any code besides the testcases. Best regards, Thomas On Mon, 19 Nov 2018 at 09:57, Thomas Preudhomme <thomas.preudhomme@linaro.org> wrote: > > Softfloat single precision and double precision floating-point > multiplication routines in libgcc share some code with the > floating-point division of their corresponding precision. As the code > is structured now, this leads to *all* division code being pulled in an > executable in softfloat mode even if only multiplication is > performed. > > This patch create some new LIB1ASMFUNCS macros to also build files with > just the multiplication and shared code as weak symbols. By putting > these earlier in the static library, they can then be picked up when > only multiplication is used and they are overriden by the global > definition in the existing file containing both multiplication and > division code when division is needed. > > The patch also removes changes made to the FUNC_START and ARM_FUNC_START > macros in r218124 since the intent was to put multiplication and > division code into their own section in a later patch to achieve the > same size optimization. That approach relied on specific section layout > to ensure multiplication and division were not too far from the shared > bit of code in order to the branches to be within range. Due to lack of > guarantee regarding section layout, in particular with all the > possibility of linker scripts, this approach was chosen instead. This > patch keeps the two testcases that were posted by Tony Wang (an Arm > employee at the time) on the mailing list to implement this approach > and adds a new one, hence the attribution. > > ChangeLog entries are as follows: > > *** gcc/ChangeLog *** > > 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * config/arm/elf.h: Update comment about condition that need to > match with libgcc/config/arm/lib1funcs.S to also include > libgcc/config/arm/t-arm. > * doc/sourcebuild.texi (output-exists, output-exists-not): Rename > subsubsection these directives are in to "Check for output files". > Move scan-symbol to that section and add to it new scan-symbol-not > directive. > > *** gcc/testsuite/ChangeLog *** > > 2018-11-16 Tony Wang <tony.wang@arm.com> > Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * lib/lto.exp (lto-execute): Define output_file and testname_with_flags > to same value as execname. > (scan-symbol): Move and rename to ... > * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a > helper function returning true or false if a symbol is present. > (scan-symbol): New procedure. > (scan-symbol-not): Likewise. > * gcc.target/arm/size-optimization-ieee-1.c: New testcase. > * gcc.target/arm/size-optimization-ieee-2.c: Likewise. > * gcc.target/arm/size-optimization-ieee-3.c: Likewise. > > *** libgcc/ChangeLog *** > > 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section > parameter and corresponding code. > (ARM_FUNC_START): Likewise in both definitions. > Also update footer comment about condition that need to match with > gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. > * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is > defined. Weakly define it in this case. > * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. > * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and > _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add > comment to keep condition in sync with the one in > libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. > > Testing: Bootstrapped on arm-linux-gnueabihf (Arm & Thumb-2) and > testsuite shows no > regression. Also built an arm-none-eabi cross compiler targeting > soft-float which also shows no regression. In particular newly added > tests and gcc.dg/lto/20081212-1 test pass. > > Is this ok for stage3? > > Best regards, > > Thomas
Ping? Best regards, Thomas On Mon, 19 Nov 2018 at 10:51, Thomas Preudhomme <thomas.preudhomme@linaro.org> wrote: > > FWIW, the testcases were taken from > https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01026.html > > Previous approach for fixing tying of fmul to fdiv can be seen in > https://gcc.gnu.org/ml/gcc-patches/2015-04/msg01971.html. As mentioned > in the cover letter, this patch went for a completely different > approach and does not share any code besides the testcases. > > Best regards, > > Thomas > On Mon, 19 Nov 2018 at 09:57, Thomas Preudhomme > <thomas.preudhomme@linaro.org> wrote: > > > > Softfloat single precision and double precision floating-point > > multiplication routines in libgcc share some code with the > > floating-point division of their corresponding precision. As the code > > is structured now, this leads to *all* division code being pulled in an > > executable in softfloat mode even if only multiplication is > > performed. > > > > This patch create some new LIB1ASMFUNCS macros to also build files with > > just the multiplication and shared code as weak symbols. By putting > > these earlier in the static library, they can then be picked up when > > only multiplication is used and they are overriden by the global > > definition in the existing file containing both multiplication and > > division code when division is needed. > > > > The patch also removes changes made to the FUNC_START and ARM_FUNC_START > > macros in r218124 since the intent was to put multiplication and > > division code into their own section in a later patch to achieve the > > same size optimization. That approach relied on specific section layout > > to ensure multiplication and division were not too far from the shared > > bit of code in order to the branches to be within range. Due to lack of > > guarantee regarding section layout, in particular with all the > > possibility of linker scripts, this approach was chosen instead. This > > patch keeps the two testcases that were posted by Tony Wang (an Arm > > employee at the time) on the mailing list to implement this approach > > and adds a new one, hence the attribution. > > > > ChangeLog entries are as follows: > > > > *** gcc/ChangeLog *** > > > > 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * config/arm/elf.h: Update comment about condition that need to > > match with libgcc/config/arm/lib1funcs.S to also include > > libgcc/config/arm/t-arm. > > * doc/sourcebuild.texi (output-exists, output-exists-not): Rename > > subsubsection these directives are in to "Check for output files". > > Move scan-symbol to that section and add to it new scan-symbol-not > > directive. > > > > *** gcc/testsuite/ChangeLog *** > > > > 2018-11-16 Tony Wang <tony.wang@arm.com> > > Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * lib/lto.exp (lto-execute): Define output_file and testname_with_flags > > to same value as execname. > > (scan-symbol): Move and rename to ... > > * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a > > helper function returning true or false if a symbol is present. > > (scan-symbol): New procedure. > > (scan-symbol-not): Likewise. > > * gcc.target/arm/size-optimization-ieee-1.c: New testcase. > > * gcc.target/arm/size-optimization-ieee-2.c: Likewise. > > * gcc.target/arm/size-optimization-ieee-3.c: Likewise. > > > > *** libgcc/ChangeLog *** > > > > 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section > > parameter and corresponding code. > > (ARM_FUNC_START): Likewise in both definitions. > > Also update footer comment about condition that need to match with > > gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. > > * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is > > defined. Weakly define it in this case. > > * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. > > * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and > > _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add > > comment to keep condition in sync with the one in > > libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. > > > > Testing: Bootstrapped on arm-linux-gnueabihf (Arm & Thumb-2) and > > testsuite shows no > > regression. Also built an arm-none-eabi cross compiler targeting > > soft-float which also shows no regression. In particular newly added > > tests and gcc.dg/lto/20081212-1 test pass. > > > > Is this ok for stage3? > > > > Best regards, > > > > Thomas From 8740697791f99b7175e188f049663883c39e51b0 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme <thomas.preudhomme@linaro.org> Date: Fri, 26 Oct 2018 16:21:09 +0100 Subject: [PATCH] [PATCH, libgcc/ARM] Optimize executable size when using softfloat fmul/dmul Softfloat single precision and double precision floating-point multiplication routines in libgcc share some code with the floating-point division of their corresponding precision. As the code is structured now, this leads to *all* division code being pulled in an executable in softfloat mode even if only multiplication is performed. This patch create some new LIB1ASMFUNCS macros to also build files with just the multiplication and shared code as weak symbols. By putting these earlier in the static library, they can then be picked up when only multiplication is used and they are overriden by the global definition in the existing file containing both multiplication and division code when division is needed. The patch also removes changes made to the FUNC_START and ARM_FUNC_START macros in r218124 since the intent was to put multiplication and division code into their own section in a later patch to achieve the same size optimization. That approach relied on specific section layout to ensure multiplication and division were not too far from the shared bit of code in order to the branches to be within range. Due to lack of guarantee regarding section layout, in particular with all the possibility of linker scripts, this approach was chosen instead. This patch keeps the two testcases that were posted by Tony Wang (an Arm employee at the time) on the mailing list to implement this approach and adds a new one, hence the attribution. ChangeLog entries are as follows: *** gcc/ChangeLog *** 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> * config/arm/elf.h: Update comment about condition that need to match with libgcc/config/arm/lib1funcs.S to also include libgcc/config/arm/t-arm. * doc/sourcebuild.texi (output-exists, output-exists-not): Rename subsubsection these directives are in to "Check for output files". Move scan-symbol to that section and add to it new scan-symbol-not directive. *** gcc/testsuite/ChangeLog *** 2018-11-16 Tony Wang <tony.wang@arm.com> Thomas Preud'homme <thomas.preudhomme@linaro.org> * lib/lto.exp (lto-execute): Define output_file and testname_with_flags to same value as execname. (scan-symbol): Move and rename to ... * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a helper function returning true or false if a symbol is present. (scan-symbol): New procedure. (scan-symbol-not): Likewise. * gcc.target/arm/size-optimization-ieee-1.c: New testcase. * gcc.target/arm/size-optimization-ieee-2.c: Likewise. * gcc.target/arm/size-optimization-ieee-3.c: Likewise. *** libgcc/ChangeLog *** 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section parameter and corresponding code. (ARM_FUNC_START): Likewise in both definitions. Also update footer comment about condition that need to match with gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is defined. Weakly define it in this case. * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add comment to keep condition in sync with the one in libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. Testing: Bootstrapped on arm-linux-gnueabihf and testsuite shows no regression. Also built an arm-none-eabi cross compiler targeting soft-float which also shows no regression. In particular newly added tests and gcc.dg/lto/20081212-1 test pass. Is this ok for stage3? Best regards, Thomas --- gcc/config/arm/elf.h | 2 +- gcc/doc/sourcebuild.texi | 9 +-- .../gcc.target/arm/size-optimization-ieee-1.c | 33 ++++++++ .../gcc.target/arm/size-optimization-ieee-2.c | 31 ++++++++ .../gcc.target/arm/size-optimization-ieee-3.c | 33 ++++++++ gcc/testsuite/lib/gcc-dg.exp | 76 +++++++++++++++++++ gcc/testsuite/lib/lto.exp | 63 +++------------ libgcc/config/arm/ieee754-df.S | 17 ++++- libgcc/config/arm/ieee754-sf.S | 16 +++- libgcc/config/arm/lib1funcs.S | 19 ++--- libgcc/config/arm/t-elf | 16 ++++ 11 files changed, 243 insertions(+), 72 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h index ad3651ba841..1e00e99afc6 100644 --- a/gcc/config/arm/elf.h +++ b/gcc/config/arm/elf.h @@ -137,7 +137,7 @@ /* Horrible hack: We want to prevent some libgcc routines being included for some multilibs. The condition should match the one in - libgcc/config/arm/lib1funcs.S. */ + libgcc/config/arm/lib1funcs.S and libgcc/config/arm/t-elf. */ #if __ARM_ARCH_ISA_ARM || __ARM_ARCH_ISA_THUMB != 1 #undef L_fixdfsi #undef L_fixunsdfsi diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 89157079ffb..9bf59b81d87 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2638,7 +2638,7 @@ Passes if @var{regex} does not match demangled text in the dump file with suffix @var{suffix}. @end table -@subsubsection Verify that an output files exists or not +@subsubsection Check for output files @table @code @item output-exists [@{ target/xfail @var{selector} @}] @@ -2646,13 +2646,12 @@ Passes if compiler output file exists. @item output-exists-not [@{ target/xfail @var{selector} @}] Passes if compiler output file does not exist. -@end table - -@subsubsection Check for LTO tests -@table @code @item scan-symbol @var{regexp} [@{ target/xfail @var{selector} @}] Passes if the pattern is present in the final executable. + +@item scan-symbol-not @var{regexp} [@{ target/xfail @var{selector} @}] +Passes if the pattern is absent from the final executable. @end table @subsubsection Checks for @command{gcov} tests diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c new file mode 100644 index 00000000000..34090f20fec --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c @@ -0,0 +1,33 @@ +/* { dg-do link { target arm_soft_ok } } */ +/* { dg-options "-mfloat-abi=soft" } */ + +int +foo (void) +{ + volatile float a; + volatile float b; + volatile float c = a * b; + return 0; +} + +int +bar (void) +{ + volatile double a; + volatile double b; + volatile double c = a * b; + return 0; +} + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ +/* { dg-final { scan-symbol-not "__aeabi_fdiv" } } */ +/* { dg-final { scan-symbol-not "__aeabi_ddiv" } } */ diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c new file mode 100644 index 00000000000..75337894a9c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c @@ -0,0 +1,31 @@ +/* { dg-do link { target arm_soft_ok } } */ +/* { dg-options "-mfloat-abi=soft" } */ + +int +foo (void) +{ + volatile float a; + volatile float b; + volatile float c = a / b; + return 0; +} + +int +bar (void) +{ + volatile double a; + volatile double b; + volatile double c = a / b; + return 0; +} + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c new file mode 100644 index 00000000000..63c92b3bbb7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c @@ -0,0 +1,33 @@ +/* { dg-do link { target arm_soft_ok } } */ +/* { dg-options "-mfloat-abi=soft" } */ + +int +foo (void) +{ + volatile float a; + volatile float b; + volatile float c = a * b + a / b; + return 0; +} + +int +bar (void) +{ + volatile double a; + volatile double b; + volatile double c = a * b + a / b; + return 0; +} + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index c33a50c0b13..0472b63f94c 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -1236,5 +1236,81 @@ proc gdb-exists { args } { return 0; } +# Helper function for scan-symbol and scan-symbol-not. It scans a symbol in +# the final executable and return 1 if present, otherwise fail. +# +# Argument 0 is the regexp to match. +# Argument 1 handles expected failures and the like +proc scan-symbol-common { scan_directive args } { + global nm + global base_dir + + # Access variable from gcc-dg-test-1 or lto-execute. + upvar 3 output_file output_file + + if { [llength $args] >= 2 } { + switch [dg-process-target [lindex $args 1]] { + "S" { } + "N" { return } + "F" { setup_xfail "*-*-*" } + "P" { } + } + } + + # Find nm like we find g++ in g++.exp. + if ![info exists nm] { + set nm [findfile $base_dir/../../../binutils/nm \ + $base_dir/../../../binutils/nm \ + [findfile $base_dir/../../nm $base_dir/../../nm \ + [findfile $base_dir/nm $base_dir/nm \ + [transform nm]]]] + verbose -log "nm is $nm" + } + + set output_file "[glob -nocomplain $output_file]" + if { $output_file == "" } { + fail "$scan_directive $args: output file does not exist" + return + } + + set fd [open "| $nm $output_file" r] + set text [read $fd] + close $fd + + if [regexp -- [lindex $args 0] $text] { + return 1 + } else { + return 0 + } +} + +# Utility for scanning a symbol in the final executable, invoked via dg-final. +# Call pass if pattern is present, otherwise fail. +# +# Argument 0 is the regexp to match. +# Argument 1 handles expected failures and the like +proc scan-symbol { args } { + set testcase [testname-for-summary] + if { [scan-symbol-common "scan-symbol" $args]} { + pass "$testcase scan-symbol $args" + } else { + fail "$testcase scan-symbol $args" + } +} + +# Utility for scanning a symbol in the final executable, invoked via dg-final. +# Call pass if pattern is absent, otherwise fail. +# +# Argument 0 is the regexp to match. +# Argument 1 handles expected failures and the like +proc scan-symbol-not { args } { + set testcase [testname-for-summary] + if { [scan-symbol-common "scan-symbol-not" $args]} { + fail "$testcase scan-symbol-not $args" + } else { + pass "$testcase scan-symbol-not $args" + } +} + set additional_prunes "" set dg_runtest_extra_prunes "" diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp index 58a84aa1936..c2c35698827 100644 --- a/gcc/testsuite/lib/lto.exp +++ b/gcc/testsuite/lib/lto.exp @@ -712,6 +712,17 @@ proc lto-execute { src1 sid } { # There's a unique name for each executable we generate. set execname "${execbase}-${count}1.exe" + + # The LTO tests don't use dg-test, so testname_with_flags and + # output_file need to be defined explicitly for each file. scan-symbol + # directives rely on both of these to be defined to find the symbol to + # scan and for the text to print in the PASS/FAIL since they can also + # be called from dg-test. testname_with_flags is also used via + # testname-for-summary when calling into generic function below to + # clean temporary files. + set output_file $execname + set testname_with_flags $execname + incr count file_on_host delete $execname @@ -774,11 +785,7 @@ proc lto-execute { src1 sid } { } } - # Clean up after -save-temps. The LTO tests don't use dg-test, so - # testname-for-summary needs to be defined explicitly for each - # file that needs to be removed. - set testname_with_flags $execname - + # Clean up after -save-temps. eval "cleanup-saved-temps" for {set i 0} {$i < $num_srcs} {incr i} { @@ -801,52 +808,6 @@ proc lto-execute { src1 sid } { } } -# Utility for scanning a symbol in the final executable, invoked via dg-final. -# Call pass if pattern is present, otherwise fail. -# -# Argument 0 is the regexp to match. -# Argument 1 handles expected failures and the like -proc scan-symbol { args } { - global nm - global base_dir - upvar 2 execname execname - - if { [llength $args] >= 2 } { - switch [dg-process-target [lindex $args 1]] { - "S" { } - "N" { return } - "F" { setup_xfail "*-*-*" } - "P" { } - } - } - - # Find nm like we find g++ in g++.exp. - if ![info exists nm] { - set nm [findfile $base_dir/../../../binutils/nm \ - $base_dir/../../../binutils/nm \ - [findfile $base_dir/../../nm $base_dir/../../nm \ - [findfile $base_dir/nm $base_dir/nm \ - [transform nm]]]] - verbose -log "nm is $nm" - } - - set output_file "[glob -nocomplain $execname]" - if { $output_file == "" } { - fail "scan-symbol $args: dump file does not exist" - return - } - - set fd [open "| $nm $output_file" r] - set text [read $fd] - close $fd - - if [regexp -- [lindex $args 0] $text] { - pass "scan-symbol $args" - } else { - fail "scan-symbol $args" - } -} - # Call pass if object readelf is ok, otherwise fail. # example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */ proc object-readelf { args } { diff --git a/libgcc/config/arm/ieee754-df.S b/libgcc/config/arm/ieee754-df.S index 480e33da31f..9f2ae9ed698 100644 --- a/libgcc/config/arm/ieee754-df.S +++ b/libgcc/config/arm/ieee754-df.S @@ -617,7 +617,18 @@ ARM_FUNC_ALIAS aeabi_l2d floatdidf #endif /* L_addsubdf3 */ -#ifdef L_arm_muldivdf3 +#if defined(L_arm_muldf3) || defined(L_arm_muldivdf3) + +@ Define multiplication as weak in _arm_muldf3.o so that it can be overriden +@ by the global definition in _arm_muldivdf3.o. This allows a program only +@ using multiplication to take the weak definition which does not contain the +@ division code. Programs using only division or both division and +@ multiplication will pull _arm_muldivdf3.o from which both the multiplication +@ and division are taken thanks to the override. +#ifdef L_arm_muldf3 +WEAK muldf3 +WEAK aeabi_dmul +#endif ARM_FUNC_START muldf3 ARM_FUNC_ALIAS aeabi_dmul muldf3 @@ -719,6 +730,7 @@ LSYM(Lml_1): orr xh, xh, #0x00100000 mov lr, #0 subs r4, r4, #1 + LSYM(Lml_u): @ Overflow? bgt LSYM(Lml_o) @@ -870,6 +882,8 @@ LSYM(Lml_n): FUNC_END aeabi_dmul FUNC_END muldf3 +#ifdef L_arm_muldivdf3 + ARM_FUNC_START divdf3 ARM_FUNC_ALIAS aeabi_ddiv divdf3 CFI_START_FUNCTION @@ -1067,6 +1081,7 @@ LSYM(Ldv_s): FUNC_END divdf3 #endif /* L_muldivdf3 */ +#endif /* L_arm_muldf3 || L_arm_muldivdf3 */ #ifdef L_arm_cmpdf2 diff --git a/libgcc/config/arm/ieee754-sf.S b/libgcc/config/arm/ieee754-sf.S index 28e0d793281..0b4d1ab377d 100644 --- a/libgcc/config/arm/ieee754-sf.S +++ b/libgcc/config/arm/ieee754-sf.S @@ -428,7 +428,18 @@ ARM_FUNC_ALIAS aeabi_l2f floatdisf #endif /* L_addsubsf3 */ -#ifdef L_arm_muldivsf3 +#if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3) + +@ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden +@ by the global definition in _arm_muldivsf3.o. This allows a program only +@ using multiplication to take the weak definition which does not contain the +@ division code. Programs using only division or both division and +@ multiplication will pull _arm_muldivsf3.o from which both the multiplication +@ and division are taken thanks to the override. +#ifdef L_arm_mulsf3 +WEAK mulsf3 +WEAK aeabi_fmul +#endif ARM_FUNC_START mulsf3 ARM_FUNC_ALIAS aeabi_fmul mulsf3 @@ -613,6 +624,8 @@ LSYM(Lml_n): FUNC_END aeabi_fmul FUNC_END mulsf3 +#ifdef L_arm_muldivsf3 + ARM_FUNC_START divsf3 ARM_FUNC_ALIAS aeabi_fdiv divsf3 CFI_START_FUNCTION @@ -756,6 +769,7 @@ LSYM(Ldv_s): FUNC_END divsf3 #endif /* L_muldivsf3 */ +#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */ #ifdef L_arm_cmpsf2 diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S index ff06d504a4c..193fb251fdb 100644 --- a/libgcc/config/arm/lib1funcs.S +++ b/libgcc/config/arm/lib1funcs.S @@ -359,12 +359,8 @@ SYM (\name): #define THUMB_SYNTAX #endif -.macro FUNC_START name sp_section= - .ifc \sp_section, function_section - .section .text.__\name,"ax",%progbits - .else +.macro FUNC_START name .text - .endif .globl SYM (__\name) TYPE (__\name) .align 0 @@ -390,8 +386,8 @@ SYM (\name): #if defined(__thumb2__) /* For Thumb-2 we build everything in thumb mode. */ -.macro ARM_FUNC_START name sp_section= - FUNC_START \name \sp_section +.macro ARM_FUNC_START name + FUNC_START \name .syntax unified .endm #define EQUIV .thumb_set @@ -422,12 +418,8 @@ _L__\name: #ifdef NOT_ISA_TARGET_32BIT #define EQUIV .thumb_set #else -.macro ARM_FUNC_START name sp_section= - .ifc \sp_section, function_section - .section .text.__\name,"ax",%progbits - .else +.macro ARM_FUNC_START name .text - .endif .globl SYM (__\name) TYPE (__\name) .align 0 @@ -2169,7 +2161,8 @@ LSYM(Lchange_\register): .endm #ifndef __symbian__ -/* The condition here must match the one in gcc/config/arm/elf.h. */ +/* The condition here must match the one in gcc/config/arm/elf.h and + libgcc/config/arm/t-elf. */ #ifndef NOT_ISA_TARGET_32BIT #include "ieee754-df.S" #include "ieee754-sf.S" diff --git a/libgcc/config/arm/t-elf b/libgcc/config/arm/t-elf index 9e7a3170f17..9da6cd37054 100644 --- a/libgcc/config/arm/t-elf +++ b/libgcc/config/arm/t-elf @@ -1,3 +1,19 @@ +ifeq (,$(findstring __symbian__,$(shell $(gcc_compile_bare) -dM -E - </dev/null))) + +ARM_ISA:=$(findstring __ARM_ARCH_ISA_ARM,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) +THUMB1_ISA:=$(findstring __ARM_ARCH_ISA_THUMB 1,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) + +# The condition here must match the one in gcc/config/arm/elf.h and +# libgcc/config/arm/lib1funcs.S. _arm_muldf3 and _arm_mulsf3 must be included +# first so that the weak multiplication symbols in the corresponding files are +# chosen over the global symbols that _arm_muldivdf3 and _arm_muldivsf3 +# inclusion create when only multiplication is used, thus avoiding pulling in +# useless division code. +ifneq (__ARM_ARCH_ISA_THUMB 1,$(ARM_ISA)$(THUMB1_ISA)) +LIB1ASMFUNCS += _arm_muldf3 _arm_mulsf3 +endif +endif # !__symbian__ + # For most CPUs we have an assembly soft-float implementations. # However this is not true for ARMv6M. Here we want to use the soft-fp C # implementation. The soft-fp code is only build for ARMv6M. This pulls
On Nov 26, 2018, at 1:46 AM, Thomas Preudhomme <thomas.preudhomme@linaro.org> wrote: > Ping? The testsuite parts are Ok. > On Mon, 19 Nov 2018 at 10:51, Thomas Preudhomme > <thomas.preudhomme@linaro.org> wrote: >> >> FWIW, the testcases were taken from >> https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01026.html
On 19/11/2018 09:57, Thomas Preudhomme wrote: > Softfloat single precision and double precision floating-point > multiplication routines in libgcc share some code with the > floating-point division of their corresponding precision. As the code > is structured now, this leads to *all* division code being pulled in an > executable in softfloat mode even if only multiplication is > performed. > > This patch create some new LIB1ASMFUNCS macros to also build files with > just the multiplication and shared code as weak symbols. By putting > these earlier in the static library, they can then be picked up when > only multiplication is used and they are overriden by the global > definition in the existing file containing both multiplication and > division code when division is needed. > > The patch also removes changes made to the FUNC_START and ARM_FUNC_START > macros in r218124 since the intent was to put multiplication and > division code into their own section in a later patch to achieve the > same size optimization. That approach relied on specific section layout > to ensure multiplication and division were not too far from the shared > bit of code in order to the branches to be within range. Due to lack of > guarantee regarding section layout, in particular with all the > possibility of linker scripts, this approach was chosen instead. This > patch keeps the two testcases that were posted by Tony Wang (an Arm > employee at the time) on the mailing list to implement this approach > and adds a new one, hence the attribution. > > ChangeLog entries are as follows: > > *** gcc/ChangeLog *** > > 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * config/arm/elf.h: Update comment about condition that need to > match with libgcc/config/arm/lib1funcs.S to also include > libgcc/config/arm/t-arm. > * doc/sourcebuild.texi (output-exists, output-exists-not): Rename > subsubsection these directives are in to "Check for output files". > Move scan-symbol to that section and add to it new scan-symbol-not > directive. > > *** gcc/testsuite/ChangeLog *** > > 2018-11-16 Tony Wang <tony.wang@arm.com> > Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * lib/lto.exp (lto-execute): Define output_file and testname_with_flags > to same value as execname. > (scan-symbol): Move and rename to ... > * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a > helper function returning true or false if a symbol is present. > (scan-symbol): New procedure. > (scan-symbol-not): Likewise. > * gcc.target/arm/size-optimization-ieee-1.c: New testcase. > * gcc.target/arm/size-optimization-ieee-2.c: Likewise. > * gcc.target/arm/size-optimization-ieee-3.c: Likewise. > > *** libgcc/ChangeLog *** > > 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section > parameter and corresponding code. > (ARM_FUNC_START): Likewise in both definitions. > Also update footer comment about condition that need to match with > gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. > * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is > defined. Weakly define it in this case. > * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. > * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and > _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add > comment to keep condition in sync with the one in > libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. > > Testing: Bootstrapped on arm-linux-gnueabihf (Arm & Thumb-2) and > testsuite shows no > regression. Also built an arm-none-eabi cross compiler targeting > soft-float which also shows no regression. In particular newly added > tests and gcc.dg/lto/20081212-1 test pass. Which non-elf targets have you tested? R. > > Is this ok for stage3? > > Best regards, > > Thomas > > > Optimize-size-fpmul_without_div.patch > > From 8740697791f99b7175e188f049663883c39e51b0 Mon Sep 17 00:00:00 2001 > From: Thomas Preud'homme <thomas.preudhomme@linaro.org> > Date: Fri, 26 Oct 2018 16:21:09 +0100 > Subject: [PATCH] [PATCH, libgcc/ARM] Optimize executable size when using > softfloat fmul/dmul > > Softfloat single precision and double precision floating-point > multiplication routines in libgcc share some code with the > floating-point division of their corresponding precision. As the code > is structured now, this leads to *all* division code being pulled in an > executable in softfloat mode even if only multiplication is > performed. > > This patch create some new LIB1ASMFUNCS macros to also build files with > just the multiplication and shared code as weak symbols. By putting > these earlier in the static library, they can then be picked up when > only multiplication is used and they are overriden by the global > definition in the existing file containing both multiplication and > division code when division is needed. > > The patch also removes changes made to the FUNC_START and ARM_FUNC_START > macros in r218124 since the intent was to put multiplication and > division code into their own section in a later patch to achieve the > same size optimization. That approach relied on specific section layout > to ensure multiplication and division were not too far from the shared > bit of code in order to the branches to be within range. Due to lack of > guarantee regarding section layout, in particular with all the > possibility of linker scripts, this approach was chosen instead. This > patch keeps the two testcases that were posted by Tony Wang (an Arm > employee at the time) on the mailing list to implement this approach > and adds a new one, hence the attribution. > > ChangeLog entries are as follows: > > *** gcc/ChangeLog *** > > 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * config/arm/elf.h: Update comment about condition that need to > match with libgcc/config/arm/lib1funcs.S to also include > libgcc/config/arm/t-arm. > * doc/sourcebuild.texi (output-exists, output-exists-not): Rename > subsubsection these directives are in to "Check for output files". > Move scan-symbol to that section and add to it new scan-symbol-not > directive. > > *** gcc/testsuite/ChangeLog *** > > 2018-11-16 Tony Wang <tony.wang@arm.com> > Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * lib/lto.exp (lto-execute): Define output_file and testname_with_flags > to same value as execname. > (scan-symbol): Move and rename to ... > * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a > helper function returning true or false if a symbol is present. > (scan-symbol): New procedure. > (scan-symbol-not): Likewise. > * gcc.target/arm/size-optimization-ieee-1.c: New testcase. > * gcc.target/arm/size-optimization-ieee-2.c: Likewise. > * gcc.target/arm/size-optimization-ieee-3.c: Likewise. > > *** libgcc/ChangeLog *** > > 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section > parameter and corresponding code. > (ARM_FUNC_START): Likewise in both definitions. > Also update footer comment about condition that need to match with > gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. > * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is > defined. Weakly define it in this case. > * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. > * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and > _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add > comment to keep condition in sync with the one in > libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. > > Testing: Bootstrapped on arm-linux-gnueabihf and testsuite shows no > regression. Also built an arm-none-eabi cross compiler targeting > soft-float which also shows no regression. In particular newly added > tests and gcc.dg/lto/20081212-1 test pass. > > Is this ok for stage3? > > Best regards, > > Thomas > --- > gcc/config/arm/elf.h | 2 +- > gcc/doc/sourcebuild.texi | 9 +-- > .../gcc.target/arm/size-optimization-ieee-1.c | 33 ++++++++ > .../gcc.target/arm/size-optimization-ieee-2.c | 31 ++++++++ > .../gcc.target/arm/size-optimization-ieee-3.c | 33 ++++++++ > gcc/testsuite/lib/gcc-dg.exp | 76 +++++++++++++++++++ > gcc/testsuite/lib/lto.exp | 63 +++------------ > libgcc/config/arm/ieee754-df.S | 17 ++++- > libgcc/config/arm/ieee754-sf.S | 16 +++- > libgcc/config/arm/lib1funcs.S | 19 ++--- > libgcc/config/arm/t-elf | 16 ++++ > 11 files changed, 243 insertions(+), 72 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c > create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c > create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c > > diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h > index ad3651ba841..1e00e99afc6 100644 > --- a/gcc/config/arm/elf.h > +++ b/gcc/config/arm/elf.h > @@ -137,7 +137,7 @@ > > /* Horrible hack: We want to prevent some libgcc routines being included > for some multilibs. The condition should match the one in > - libgcc/config/arm/lib1funcs.S. */ > + libgcc/config/arm/lib1funcs.S and libgcc/config/arm/t-elf. */ > #if __ARM_ARCH_ISA_ARM || __ARM_ARCH_ISA_THUMB != 1 > #undef L_fixdfsi > #undef L_fixunsdfsi > diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi > index 89157079ffb..9bf59b81d87 100644 > --- a/gcc/doc/sourcebuild.texi > +++ b/gcc/doc/sourcebuild.texi > @@ -2638,7 +2638,7 @@ Passes if @var{regex} does not match demangled text in the dump file with > suffix @var{suffix}. > @end table > > -@subsubsection Verify that an output files exists or not > +@subsubsection Check for output files > > @table @code > @item output-exists [@{ target/xfail @var{selector} @}] > @@ -2646,13 +2646,12 @@ Passes if compiler output file exists. > > @item output-exists-not [@{ target/xfail @var{selector} @}] > Passes if compiler output file does not exist. > -@end table > - > -@subsubsection Check for LTO tests > > -@table @code > @item scan-symbol @var{regexp} [@{ target/xfail @var{selector} @}] > Passes if the pattern is present in the final executable. > + > +@item scan-symbol-not @var{regexp} [@{ target/xfail @var{selector} @}] > +Passes if the pattern is absent from the final executable. > @end table > > @subsubsection Checks for @command{gcov} tests > diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c > new file mode 100644 > index 00000000000..34090f20fec > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c > @@ -0,0 +1,33 @@ > +/* { dg-do link { target arm_soft_ok } } */ > +/* { dg-options "-mfloat-abi=soft" } */ > + > +int > +foo (void) > +{ > + volatile float a; > + volatile float b; > + volatile float c = a * b; > + return 0; > +} > + > +int > +bar (void) > +{ > + volatile double a; > + volatile double b; > + volatile double c = a * b; > + return 0; > +} > + > +int > +main (void) > +{ > + foo (); > + bar (); > + return 0; > +} > + > +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ > +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ > +/* { dg-final { scan-symbol-not "__aeabi_fdiv" } } */ > +/* { dg-final { scan-symbol-not "__aeabi_ddiv" } } */ > diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c > new file mode 100644 > index 00000000000..75337894a9c > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c > @@ -0,0 +1,31 @@ > +/* { dg-do link { target arm_soft_ok } } */ > +/* { dg-options "-mfloat-abi=soft" } */ > + > +int > +foo (void) > +{ > + volatile float a; > + volatile float b; > + volatile float c = a / b; > + return 0; > +} > + > +int > +bar (void) > +{ > + volatile double a; > + volatile double b; > + volatile double c = a / b; > + return 0; > +} > + > +int > +main (void) > +{ > + foo (); > + bar (); > + return 0; > +} > + > +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ > +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ > diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c > new file mode 100644 > index 00000000000..63c92b3bbb7 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c > @@ -0,0 +1,33 @@ > +/* { dg-do link { target arm_soft_ok } } */ > +/* { dg-options "-mfloat-abi=soft" } */ > + > +int > +foo (void) > +{ > + volatile float a; > + volatile float b; > + volatile float c = a * b + a / b; > + return 0; > +} > + > +int > +bar (void) > +{ > + volatile double a; > + volatile double b; > + volatile double c = a * b + a / b; > + return 0; > +} > + > +int > +main (void) > +{ > + foo (); > + bar (); > + return 0; > +} > + > +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ > +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ > +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ > +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ > diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp > index c33a50c0b13..0472b63f94c 100644 > --- a/gcc/testsuite/lib/gcc-dg.exp > +++ b/gcc/testsuite/lib/gcc-dg.exp > @@ -1236,5 +1236,81 @@ proc gdb-exists { args } { > return 0; > } > > +# Helper function for scan-symbol and scan-symbol-not. It scans a symbol in > +# the final executable and return 1 if present, otherwise fail. > +# > +# Argument 0 is the regexp to match. > +# Argument 1 handles expected failures and the like > +proc scan-symbol-common { scan_directive args } { > + global nm > + global base_dir > + > + # Access variable from gcc-dg-test-1 or lto-execute. > + upvar 3 output_file output_file > + > + if { [llength $args] >= 2 } { > + switch [dg-process-target [lindex $args 1]] { > + "S" { } > + "N" { return } > + "F" { setup_xfail "*-*-*" } > + "P" { } > + } > + } > + > + # Find nm like we find g++ in g++.exp. > + if ![info exists nm] { > + set nm [findfile $base_dir/../../../binutils/nm \ > + $base_dir/../../../binutils/nm \ > + [findfile $base_dir/../../nm $base_dir/../../nm \ > + [findfile $base_dir/nm $base_dir/nm \ > + [transform nm]]]] > + verbose -log "nm is $nm" > + } > + > + set output_file "[glob -nocomplain $output_file]" > + if { $output_file == "" } { > + fail "$scan_directive $args: output file does not exist" > + return > + } > + > + set fd [open "| $nm $output_file" r] > + set text [read $fd] > + close $fd > + > + if [regexp -- [lindex $args 0] $text] { > + return 1 > + } else { > + return 0 > + } > +} > + > +# Utility for scanning a symbol in the final executable, invoked via dg-final. > +# Call pass if pattern is present, otherwise fail. > +# > +# Argument 0 is the regexp to match. > +# Argument 1 handles expected failures and the like > +proc scan-symbol { args } { > + set testcase [testname-for-summary] > + if { [scan-symbol-common "scan-symbol" $args]} { > + pass "$testcase scan-symbol $args" > + } else { > + fail "$testcase scan-symbol $args" > + } > +} > + > +# Utility for scanning a symbol in the final executable, invoked via dg-final. > +# Call pass if pattern is absent, otherwise fail. > +# > +# Argument 0 is the regexp to match. > +# Argument 1 handles expected failures and the like > +proc scan-symbol-not { args } { > + set testcase [testname-for-summary] > + if { [scan-symbol-common "scan-symbol-not" $args]} { > + fail "$testcase scan-symbol-not $args" > + } else { > + pass "$testcase scan-symbol-not $args" > + } > +} > + > set additional_prunes "" > set dg_runtest_extra_prunes "" > diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp > index 58a84aa1936..c2c35698827 100644 > --- a/gcc/testsuite/lib/lto.exp > +++ b/gcc/testsuite/lib/lto.exp > @@ -712,6 +712,17 @@ proc lto-execute { src1 sid } { > > # There's a unique name for each executable we generate. > set execname "${execbase}-${count}1.exe" > + > + # The LTO tests don't use dg-test, so testname_with_flags and > + # output_file need to be defined explicitly for each file. scan-symbol > + # directives rely on both of these to be defined to find the symbol to > + # scan and for the text to print in the PASS/FAIL since they can also > + # be called from dg-test. testname_with_flags is also used via > + # testname-for-summary when calling into generic function below to > + # clean temporary files. > + set output_file $execname > + set testname_with_flags $execname > + > incr count > > file_on_host delete $execname > @@ -774,11 +785,7 @@ proc lto-execute { src1 sid } { > } > } > > - # Clean up after -save-temps. The LTO tests don't use dg-test, so > - # testname-for-summary needs to be defined explicitly for each > - # file that needs to be removed. > - set testname_with_flags $execname > - > + # Clean up after -save-temps. > eval "cleanup-saved-temps" > > for {set i 0} {$i < $num_srcs} {incr i} { > @@ -801,52 +808,6 @@ proc lto-execute { src1 sid } { > } > } > > -# Utility for scanning a symbol in the final executable, invoked via dg-final. > -# Call pass if pattern is present, otherwise fail. > -# > -# Argument 0 is the regexp to match. > -# Argument 1 handles expected failures and the like > -proc scan-symbol { args } { > - global nm > - global base_dir > - upvar 2 execname execname > - > - if { [llength $args] >= 2 } { > - switch [dg-process-target [lindex $args 1]] { > - "S" { } > - "N" { return } > - "F" { setup_xfail "*-*-*" } > - "P" { } > - } > - } > - > - # Find nm like we find g++ in g++.exp. > - if ![info exists nm] { > - set nm [findfile $base_dir/../../../binutils/nm \ > - $base_dir/../../../binutils/nm \ > - [findfile $base_dir/../../nm $base_dir/../../nm \ > - [findfile $base_dir/nm $base_dir/nm \ > - [transform nm]]]] > - verbose -log "nm is $nm" > - } > - > - set output_file "[glob -nocomplain $execname]" > - if { $output_file == "" } { > - fail "scan-symbol $args: dump file does not exist" > - return > - } > - > - set fd [open "| $nm $output_file" r] > - set text [read $fd] > - close $fd > - > - if [regexp -- [lindex $args 0] $text] { > - pass "scan-symbol $args" > - } else { > - fail "scan-symbol $args" > - } > -} > - > # Call pass if object readelf is ok, otherwise fail. > # example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */ > proc object-readelf { args } { > diff --git a/libgcc/config/arm/ieee754-df.S b/libgcc/config/arm/ieee754-df.S > index 480e33da31f..9f2ae9ed698 100644 > --- a/libgcc/config/arm/ieee754-df.S > +++ b/libgcc/config/arm/ieee754-df.S > @@ -617,7 +617,18 @@ ARM_FUNC_ALIAS aeabi_l2d floatdidf > > #endif /* L_addsubdf3 */ > > -#ifdef L_arm_muldivdf3 > +#if defined(L_arm_muldf3) || defined(L_arm_muldivdf3) > + > +@ Define multiplication as weak in _arm_muldf3.o so that it can be overriden > +@ by the global definition in _arm_muldivdf3.o. This allows a program only > +@ using multiplication to take the weak definition which does not contain the > +@ division code. Programs using only division or both division and > +@ multiplication will pull _arm_muldivdf3.o from which both the multiplication > +@ and division are taken thanks to the override. > +#ifdef L_arm_muldf3 > +WEAK muldf3 > +WEAK aeabi_dmul > +#endif > > ARM_FUNC_START muldf3 > ARM_FUNC_ALIAS aeabi_dmul muldf3 > @@ -719,6 +730,7 @@ LSYM(Lml_1): > orr xh, xh, #0x00100000 > mov lr, #0 > subs r4, r4, #1 > + > LSYM(Lml_u): > @ Overflow? > bgt LSYM(Lml_o) > @@ -870,6 +882,8 @@ LSYM(Lml_n): > FUNC_END aeabi_dmul > FUNC_END muldf3 > > +#ifdef L_arm_muldivdf3 > + > ARM_FUNC_START divdf3 > ARM_FUNC_ALIAS aeabi_ddiv divdf3 > CFI_START_FUNCTION > @@ -1067,6 +1081,7 @@ LSYM(Ldv_s): > FUNC_END divdf3 > > #endif /* L_muldivdf3 */ > +#endif /* L_arm_muldf3 || L_arm_muldivdf3 */ > > #ifdef L_arm_cmpdf2 > > diff --git a/libgcc/config/arm/ieee754-sf.S b/libgcc/config/arm/ieee754-sf.S > index 28e0d793281..0b4d1ab377d 100644 > --- a/libgcc/config/arm/ieee754-sf.S > +++ b/libgcc/config/arm/ieee754-sf.S > @@ -428,7 +428,18 @@ ARM_FUNC_ALIAS aeabi_l2f floatdisf > > #endif /* L_addsubsf3 */ > > -#ifdef L_arm_muldivsf3 > +#if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3) > + > +@ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden > +@ by the global definition in _arm_muldivsf3.o. This allows a program only > +@ using multiplication to take the weak definition which does not contain the > +@ division code. Programs using only division or both division and > +@ multiplication will pull _arm_muldivsf3.o from which both the multiplication > +@ and division are taken thanks to the override. > +#ifdef L_arm_mulsf3 > +WEAK mulsf3 > +WEAK aeabi_fmul > +#endif > > ARM_FUNC_START mulsf3 > ARM_FUNC_ALIAS aeabi_fmul mulsf3 > @@ -613,6 +624,8 @@ LSYM(Lml_n): > FUNC_END aeabi_fmul > FUNC_END mulsf3 > > +#ifdef L_arm_muldivsf3 > + > ARM_FUNC_START divsf3 > ARM_FUNC_ALIAS aeabi_fdiv divsf3 > CFI_START_FUNCTION > @@ -756,6 +769,7 @@ LSYM(Ldv_s): > FUNC_END divsf3 > > #endif /* L_muldivsf3 */ > +#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */ > > #ifdef L_arm_cmpsf2 > > diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S > index ff06d504a4c..193fb251fdb 100644 > --- a/libgcc/config/arm/lib1funcs.S > +++ b/libgcc/config/arm/lib1funcs.S > @@ -359,12 +359,8 @@ SYM (\name): > #define THUMB_SYNTAX > #endif > > -.macro FUNC_START name sp_section= > - .ifc \sp_section, function_section > - .section .text.__\name,"ax",%progbits > - .else > +.macro FUNC_START name > .text > - .endif > .globl SYM (__\name) > TYPE (__\name) > .align 0 > @@ -390,8 +386,8 @@ SYM (\name): > #if defined(__thumb2__) > > /* For Thumb-2 we build everything in thumb mode. */ > -.macro ARM_FUNC_START name sp_section= > - FUNC_START \name \sp_section > +.macro ARM_FUNC_START name > + FUNC_START \name > .syntax unified > .endm > #define EQUIV .thumb_set > @@ -422,12 +418,8 @@ _L__\name: > #ifdef NOT_ISA_TARGET_32BIT > #define EQUIV .thumb_set > #else > -.macro ARM_FUNC_START name sp_section= > - .ifc \sp_section, function_section > - .section .text.__\name,"ax",%progbits > - .else > +.macro ARM_FUNC_START name > .text > - .endif > .globl SYM (__\name) > TYPE (__\name) > .align 0 > @@ -2169,7 +2161,8 @@ LSYM(Lchange_\register): > .endm > > #ifndef __symbian__ > -/* The condition here must match the one in gcc/config/arm/elf.h. */ > +/* The condition here must match the one in gcc/config/arm/elf.h and > + libgcc/config/arm/t-elf. */ > #ifndef NOT_ISA_TARGET_32BIT > #include "ieee754-df.S" > #include "ieee754-sf.S" > diff --git a/libgcc/config/arm/t-elf b/libgcc/config/arm/t-elf > index 9e7a3170f17..9da6cd37054 100644 > --- a/libgcc/config/arm/t-elf > +++ b/libgcc/config/arm/t-elf > @@ -1,3 +1,19 @@ > +ifeq (,$(findstring __symbian__,$(shell $(gcc_compile_bare) -dM -E - </dev/null))) > + > +ARM_ISA:=$(findstring __ARM_ARCH_ISA_ARM,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) > +THUMB1_ISA:=$(findstring __ARM_ARCH_ISA_THUMB 1,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) > + > +# The condition here must match the one in gcc/config/arm/elf.h and > +# libgcc/config/arm/lib1funcs.S. _arm_muldf3 and _arm_mulsf3 must be included > +# first so that the weak multiplication symbols in the corresponding files are > +# chosen over the global symbols that _arm_muldivdf3 and _arm_muldivsf3 > +# inclusion create when only multiplication is used, thus avoiding pulling in > +# useless division code. > +ifneq (__ARM_ARCH_ISA_THUMB 1,$(ARM_ISA)$(THUMB1_ISA)) > +LIB1ASMFUNCS += _arm_muldf3 _arm_mulsf3 > +endif > +endif # !__symbian__ > + > # For most CPUs we have an assembly soft-float implementations. > # However this is not true for ARMv6M. Here we want to use the soft-fp C > # implementation. The soft-fp code is only build for ARMv6M. This pulls >
Hi Richard, None, is there any? All the one I could find in the big switch selecting tm_files and tmake_files in gcc/config.gcc are including arm/elf.h. I tried to build for arm-wince-pe but got: "Configuration arm-wince-pe not supported". However note that to guarantee correct results the only requirement is to support global symbol overriding weak symbol correctly and I see .weak usage in many other libgcc backend (eg. i386). The "take the first definition resolving an undefined reference and ignore the one in following object of a static library" is only to benefit from the size optimization. Best regards, Thomas On Fri, 7 Dec 2018 at 14:14, Richard Earnshaw (lists) <Richard.Earnshaw@arm.com> wrote: > > On 19/11/2018 09:57, Thomas Preudhomme wrote: > > Softfloat single precision and double precision floating-point > > multiplication routines in libgcc share some code with the > > floating-point division of their corresponding precision. As the code > > is structured now, this leads to *all* division code being pulled in an > > executable in softfloat mode even if only multiplication is > > performed. > > > > This patch create some new LIB1ASMFUNCS macros to also build files with > > just the multiplication and shared code as weak symbols. By putting > > these earlier in the static library, they can then be picked up when > > only multiplication is used and they are overriden by the global > > definition in the existing file containing both multiplication and > > division code when division is needed. > > > > The patch also removes changes made to the FUNC_START and ARM_FUNC_START > > macros in r218124 since the intent was to put multiplication and > > division code into their own section in a later patch to achieve the > > same size optimization. That approach relied on specific section layout > > to ensure multiplication and division were not too far from the shared > > bit of code in order to the branches to be within range. Due to lack of > > guarantee regarding section layout, in particular with all the > > possibility of linker scripts, this approach was chosen instead. This > > patch keeps the two testcases that were posted by Tony Wang (an Arm > > employee at the time) on the mailing list to implement this approach > > and adds a new one, hence the attribution. > > > > ChangeLog entries are as follows: > > > > *** gcc/ChangeLog *** > > > > 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * config/arm/elf.h: Update comment about condition that need to > > match with libgcc/config/arm/lib1funcs.S to also include > > libgcc/config/arm/t-arm. > > * doc/sourcebuild.texi (output-exists, output-exists-not): Rename > > subsubsection these directives are in to "Check for output files". > > Move scan-symbol to that section and add to it new scan-symbol-not > > directive. > > > > *** gcc/testsuite/ChangeLog *** > > > > 2018-11-16 Tony Wang <tony.wang@arm.com> > > Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * lib/lto.exp (lto-execute): Define output_file and testname_with_flags > > to same value as execname. > > (scan-symbol): Move and rename to ... > > * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a > > helper function returning true or false if a symbol is present. > > (scan-symbol): New procedure. > > (scan-symbol-not): Likewise. > > * gcc.target/arm/size-optimization-ieee-1.c: New testcase. > > * gcc.target/arm/size-optimization-ieee-2.c: Likewise. > > * gcc.target/arm/size-optimization-ieee-3.c: Likewise. > > > > *** libgcc/ChangeLog *** > > > > 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section > > parameter and corresponding code. > > (ARM_FUNC_START): Likewise in both definitions. > > Also update footer comment about condition that need to match with > > gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. > > * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is > > defined. Weakly define it in this case. > > * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. > > * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and > > _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add > > comment to keep condition in sync with the one in > > libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. > > > > Testing: Bootstrapped on arm-linux-gnueabihf (Arm & Thumb-2) and > > testsuite shows no > > regression. Also built an arm-none-eabi cross compiler targeting > > soft-float which also shows no regression. In particular newly added > > tests and gcc.dg/lto/20081212-1 test pass. > > Which non-elf targets have you tested? > > R. > > > > > Is this ok for stage3? > > > > Best regards, > > > > Thomas > > > > > > Optimize-size-fpmul_without_div.patch > > > > From 8740697791f99b7175e188f049663883c39e51b0 Mon Sep 17 00:00:00 2001 > > From: Thomas Preud'homme <thomas.preudhomme@linaro.org> > > Date: Fri, 26 Oct 2018 16:21:09 +0100 > > Subject: [PATCH] [PATCH, libgcc/ARM] Optimize executable size when using > > softfloat fmul/dmul > > > > Softfloat single precision and double precision floating-point > > multiplication routines in libgcc share some code with the > > floating-point division of their corresponding precision. As the code > > is structured now, this leads to *all* division code being pulled in an > > executable in softfloat mode even if only multiplication is > > performed. > > > > This patch create some new LIB1ASMFUNCS macros to also build files with > > just the multiplication and shared code as weak symbols. By putting > > these earlier in the static library, they can then be picked up when > > only multiplication is used and they are overriden by the global > > definition in the existing file containing both multiplication and > > division code when division is needed. > > > > The patch also removes changes made to the FUNC_START and ARM_FUNC_START > > macros in r218124 since the intent was to put multiplication and > > division code into their own section in a later patch to achieve the > > same size optimization. That approach relied on specific section layout > > to ensure multiplication and division were not too far from the shared > > bit of code in order to the branches to be within range. Due to lack of > > guarantee regarding section layout, in particular with all the > > possibility of linker scripts, this approach was chosen instead. This > > patch keeps the two testcases that were posted by Tony Wang (an Arm > > employee at the time) on the mailing list to implement this approach > > and adds a new one, hence the attribution. > > > > ChangeLog entries are as follows: > > > > *** gcc/ChangeLog *** > > > > 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * config/arm/elf.h: Update comment about condition that need to > > match with libgcc/config/arm/lib1funcs.S to also include > > libgcc/config/arm/t-arm. > > * doc/sourcebuild.texi (output-exists, output-exists-not): Rename > > subsubsection these directives are in to "Check for output files". > > Move scan-symbol to that section and add to it new scan-symbol-not > > directive. > > > > *** gcc/testsuite/ChangeLog *** > > > > 2018-11-16 Tony Wang <tony.wang@arm.com> > > Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * lib/lto.exp (lto-execute): Define output_file and testname_with_flags > > to same value as execname. > > (scan-symbol): Move and rename to ... > > * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a > > helper function returning true or false if a symbol is present. > > (scan-symbol): New procedure. > > (scan-symbol-not): Likewise. > > * gcc.target/arm/size-optimization-ieee-1.c: New testcase. > > * gcc.target/arm/size-optimization-ieee-2.c: Likewise. > > * gcc.target/arm/size-optimization-ieee-3.c: Likewise. > > > > *** libgcc/ChangeLog *** > > > > 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> > > > > * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section > > parameter and corresponding code. > > (ARM_FUNC_START): Likewise in both definitions. > > Also update footer comment about condition that need to match with > > gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. > > * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is > > defined. Weakly define it in this case. > > * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. > > * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and > > _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add > > comment to keep condition in sync with the one in > > libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. > > > > Testing: Bootstrapped on arm-linux-gnueabihf and testsuite shows no > > regression. Also built an arm-none-eabi cross compiler targeting > > soft-float which also shows no regression. In particular newly added > > tests and gcc.dg/lto/20081212-1 test pass. > > > > Is this ok for stage3? > > > > Best regards, > > > > Thomas > > --- > > gcc/config/arm/elf.h | 2 +- > > gcc/doc/sourcebuild.texi | 9 +-- > > .../gcc.target/arm/size-optimization-ieee-1.c | 33 ++++++++ > > .../gcc.target/arm/size-optimization-ieee-2.c | 31 ++++++++ > > .../gcc.target/arm/size-optimization-ieee-3.c | 33 ++++++++ > > gcc/testsuite/lib/gcc-dg.exp | 76 +++++++++++++++++++ > > gcc/testsuite/lib/lto.exp | 63 +++------------ > > libgcc/config/arm/ieee754-df.S | 17 ++++- > > libgcc/config/arm/ieee754-sf.S | 16 +++- > > libgcc/config/arm/lib1funcs.S | 19 ++--- > > libgcc/config/arm/t-elf | 16 ++++ > > 11 files changed, 243 insertions(+), 72 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c > > create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c > > create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c > > > > diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h > > index ad3651ba841..1e00e99afc6 100644 > > --- a/gcc/config/arm/elf.h > > +++ b/gcc/config/arm/elf.h > > @@ -137,7 +137,7 @@ > > > > /* Horrible hack: We want to prevent some libgcc routines being included > > for some multilibs. The condition should match the one in > > - libgcc/config/arm/lib1funcs.S. */ > > + libgcc/config/arm/lib1funcs.S and libgcc/config/arm/t-elf. */ > > #if __ARM_ARCH_ISA_ARM || __ARM_ARCH_ISA_THUMB != 1 > > #undef L_fixdfsi > > #undef L_fixunsdfsi > > diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi > > index 89157079ffb..9bf59b81d87 100644 > > --- a/gcc/doc/sourcebuild.texi > > +++ b/gcc/doc/sourcebuild.texi > > @@ -2638,7 +2638,7 @@ Passes if @var{regex} does not match demangled text in the dump file with > > suffix @var{suffix}. > > @end table > > > > -@subsubsection Verify that an output files exists or not > > +@subsubsection Check for output files > > > > @table @code > > @item output-exists [@{ target/xfail @var{selector} @}] > > @@ -2646,13 +2646,12 @@ Passes if compiler output file exists. > > > > @item output-exists-not [@{ target/xfail @var{selector} @}] > > Passes if compiler output file does not exist. > > -@end table > > - > > -@subsubsection Check for LTO tests > > > > -@table @code > > @item scan-symbol @var{regexp} [@{ target/xfail @var{selector} @}] > > Passes if the pattern is present in the final executable. > > + > > +@item scan-symbol-not @var{regexp} [@{ target/xfail @var{selector} @}] > > +Passes if the pattern is absent from the final executable. > > @end table > > > > @subsubsection Checks for @command{gcov} tests > > diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c > > new file mode 100644 > > index 00000000000..34090f20fec > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c > > @@ -0,0 +1,33 @@ > > +/* { dg-do link { target arm_soft_ok } } */ > > +/* { dg-options "-mfloat-abi=soft" } */ > > + > > +int > > +foo (void) > > +{ > > + volatile float a; > > + volatile float b; > > + volatile float c = a * b; > > + return 0; > > +} > > + > > +int > > +bar (void) > > +{ > > + volatile double a; > > + volatile double b; > > + volatile double c = a * b; > > + return 0; > > +} > > + > > +int > > +main (void) > > +{ > > + foo (); > > + bar (); > > + return 0; > > +} > > + > > +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ > > +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ > > +/* { dg-final { scan-symbol-not "__aeabi_fdiv" } } */ > > +/* { dg-final { scan-symbol-not "__aeabi_ddiv" } } */ > > diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c > > new file mode 100644 > > index 00000000000..75337894a9c > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c > > @@ -0,0 +1,31 @@ > > +/* { dg-do link { target arm_soft_ok } } */ > > +/* { dg-options "-mfloat-abi=soft" } */ > > + > > +int > > +foo (void) > > +{ > > + volatile float a; > > + volatile float b; > > + volatile float c = a / b; > > + return 0; > > +} > > + > > +int > > +bar (void) > > +{ > > + volatile double a; > > + volatile double b; > > + volatile double c = a / b; > > + return 0; > > +} > > + > > +int > > +main (void) > > +{ > > + foo (); > > + bar (); > > + return 0; > > +} > > + > > +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ > > +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ > > diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c > > new file mode 100644 > > index 00000000000..63c92b3bbb7 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c > > @@ -0,0 +1,33 @@ > > +/* { dg-do link { target arm_soft_ok } } */ > > +/* { dg-options "-mfloat-abi=soft" } */ > > + > > +int > > +foo (void) > > +{ > > + volatile float a; > > + volatile float b; > > + volatile float c = a * b + a / b; > > + return 0; > > +} > > + > > +int > > +bar (void) > > +{ > > + volatile double a; > > + volatile double b; > > + volatile double c = a * b + a / b; > > + return 0; > > +} > > + > > +int > > +main (void) > > +{ > > + foo (); > > + bar (); > > + return 0; > > +} > > + > > +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ > > +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ > > +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ > > +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ > > diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp > > index c33a50c0b13..0472b63f94c 100644 > > --- a/gcc/testsuite/lib/gcc-dg.exp > > +++ b/gcc/testsuite/lib/gcc-dg.exp > > @@ -1236,5 +1236,81 @@ proc gdb-exists { args } { > > return 0; > > } > > > > +# Helper function for scan-symbol and scan-symbol-not. It scans a symbol in > > +# the final executable and return 1 if present, otherwise fail. > > +# > > +# Argument 0 is the regexp to match. > > +# Argument 1 handles expected failures and the like > > +proc scan-symbol-common { scan_directive args } { > > + global nm > > + global base_dir > > + > > + # Access variable from gcc-dg-test-1 or lto-execute. > > + upvar 3 output_file output_file > > + > > + if { [llength $args] >= 2 } { > > + switch [dg-process-target [lindex $args 1]] { > > + "S" { } > > + "N" { return } > > + "F" { setup_xfail "*-*-*" } > > + "P" { } > > + } > > + } > > + > > + # Find nm like we find g++ in g++.exp. > > + if ![info exists nm] { > > + set nm [findfile $base_dir/../../../binutils/nm \ > > + $base_dir/../../../binutils/nm \ > > + [findfile $base_dir/../../nm $base_dir/../../nm \ > > + [findfile $base_dir/nm $base_dir/nm \ > > + [transform nm]]]] > > + verbose -log "nm is $nm" > > + } > > + > > + set output_file "[glob -nocomplain $output_file]" > > + if { $output_file == "" } { > > + fail "$scan_directive $args: output file does not exist" > > + return > > + } > > + > > + set fd [open "| $nm $output_file" r] > > + set text [read $fd] > > + close $fd > > + > > + if [regexp -- [lindex $args 0] $text] { > > + return 1 > > + } else { > > + return 0 > > + } > > +} > > + > > +# Utility for scanning a symbol in the final executable, invoked via dg-final. > > +# Call pass if pattern is present, otherwise fail. > > +# > > +# Argument 0 is the regexp to match. > > +# Argument 1 handles expected failures and the like > > +proc scan-symbol { args } { > > + set testcase [testname-for-summary] > > + if { [scan-symbol-common "scan-symbol" $args]} { > > + pass "$testcase scan-symbol $args" > > + } else { > > + fail "$testcase scan-symbol $args" > > + } > > +} > > + > > +# Utility for scanning a symbol in the final executable, invoked via dg-final. > > +# Call pass if pattern is absent, otherwise fail. > > +# > > +# Argument 0 is the regexp to match. > > +# Argument 1 handles expected failures and the like > > +proc scan-symbol-not { args } { > > + set testcase [testname-for-summary] > > + if { [scan-symbol-common "scan-symbol-not" $args]} { > > + fail "$testcase scan-symbol-not $args" > > + } else { > > + pass "$testcase scan-symbol-not $args" > > + } > > +} > > + > > set additional_prunes "" > > set dg_runtest_extra_prunes "" > > diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp > > index 58a84aa1936..c2c35698827 100644 > > --- a/gcc/testsuite/lib/lto.exp > > +++ b/gcc/testsuite/lib/lto.exp > > @@ -712,6 +712,17 @@ proc lto-execute { src1 sid } { > > > > # There's a unique name for each executable we generate. > > set execname "${execbase}-${count}1.exe" > > + > > + # The LTO tests don't use dg-test, so testname_with_flags and > > + # output_file need to be defined explicitly for each file. scan-symbol > > + # directives rely on both of these to be defined to find the symbol to > > + # scan and for the text to print in the PASS/FAIL since they can also > > + # be called from dg-test. testname_with_flags is also used via > > + # testname-for-summary when calling into generic function below to > > + # clean temporary files. > > + set output_file $execname > > + set testname_with_flags $execname > > + > > incr count > > > > file_on_host delete $execname > > @@ -774,11 +785,7 @@ proc lto-execute { src1 sid } { > > } > > } > > > > - # Clean up after -save-temps. The LTO tests don't use dg-test, so > > - # testname-for-summary needs to be defined explicitly for each > > - # file that needs to be removed. > > - set testname_with_flags $execname > > - > > + # Clean up after -save-temps. > > eval "cleanup-saved-temps" > > > > for {set i 0} {$i < $num_srcs} {incr i} { > > @@ -801,52 +808,6 @@ proc lto-execute { src1 sid } { > > } > > } > > > > -# Utility for scanning a symbol in the final executable, invoked via dg-final. > > -# Call pass if pattern is present, otherwise fail. > > -# > > -# Argument 0 is the regexp to match. > > -# Argument 1 handles expected failures and the like > > -proc scan-symbol { args } { > > - global nm > > - global base_dir > > - upvar 2 execname execname > > - > > - if { [llength $args] >= 2 } { > > - switch [dg-process-target [lindex $args 1]] { > > - "S" { } > > - "N" { return } > > - "F" { setup_xfail "*-*-*" } > > - "P" { } > > - } > > - } > > - > > - # Find nm like we find g++ in g++.exp. > > - if ![info exists nm] { > > - set nm [findfile $base_dir/../../../binutils/nm \ > > - $base_dir/../../../binutils/nm \ > > - [findfile $base_dir/../../nm $base_dir/../../nm \ > > - [findfile $base_dir/nm $base_dir/nm \ > > - [transform nm]]]] > > - verbose -log "nm is $nm" > > - } > > - > > - set output_file "[glob -nocomplain $execname]" > > - if { $output_file == "" } { > > - fail "scan-symbol $args: dump file does not exist" > > - return > > - } > > - > > - set fd [open "| $nm $output_file" r] > > - set text [read $fd] > > - close $fd > > - > > - if [regexp -- [lindex $args 0] $text] { > > - pass "scan-symbol $args" > > - } else { > > - fail "scan-symbol $args" > > - } > > -} > > - > > # Call pass if object readelf is ok, otherwise fail. > > # example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */ > > proc object-readelf { args } { > > diff --git a/libgcc/config/arm/ieee754-df.S b/libgcc/config/arm/ieee754-df.S > > index 480e33da31f..9f2ae9ed698 100644 > > --- a/libgcc/config/arm/ieee754-df.S > > +++ b/libgcc/config/arm/ieee754-df.S > > @@ -617,7 +617,18 @@ ARM_FUNC_ALIAS aeabi_l2d floatdidf > > > > #endif /* L_addsubdf3 */ > > > > -#ifdef L_arm_muldivdf3 > > +#if defined(L_arm_muldf3) || defined(L_arm_muldivdf3) > > + > > +@ Define multiplication as weak in _arm_muldf3.o so that it can be overriden > > +@ by the global definition in _arm_muldivdf3.o. This allows a program only > > +@ using multiplication to take the weak definition which does not contain the > > +@ division code. Programs using only division or both division and > > +@ multiplication will pull _arm_muldivdf3.o from which both the multiplication > > +@ and division are taken thanks to the override. > > +#ifdef L_arm_muldf3 > > +WEAK muldf3 > > +WEAK aeabi_dmul > > +#endif > > > > ARM_FUNC_START muldf3 > > ARM_FUNC_ALIAS aeabi_dmul muldf3 > > @@ -719,6 +730,7 @@ LSYM(Lml_1): > > orr xh, xh, #0x00100000 > > mov lr, #0 > > subs r4, r4, #1 > > + > > LSYM(Lml_u): > > @ Overflow? > > bgt LSYM(Lml_o) > > @@ -870,6 +882,8 @@ LSYM(Lml_n): > > FUNC_END aeabi_dmul > > FUNC_END muldf3 > > > > +#ifdef L_arm_muldivdf3 > > + > > ARM_FUNC_START divdf3 > > ARM_FUNC_ALIAS aeabi_ddiv divdf3 > > CFI_START_FUNCTION > > @@ -1067,6 +1081,7 @@ LSYM(Ldv_s): > > FUNC_END divdf3 > > > > #endif /* L_muldivdf3 */ > > +#endif /* L_arm_muldf3 || L_arm_muldivdf3 */ > > > > #ifdef L_arm_cmpdf2 > > > > diff --git a/libgcc/config/arm/ieee754-sf.S b/libgcc/config/arm/ieee754-sf.S > > index 28e0d793281..0b4d1ab377d 100644 > > --- a/libgcc/config/arm/ieee754-sf.S > > +++ b/libgcc/config/arm/ieee754-sf.S > > @@ -428,7 +428,18 @@ ARM_FUNC_ALIAS aeabi_l2f floatdisf > > > > #endif /* L_addsubsf3 */ > > > > -#ifdef L_arm_muldivsf3 > > +#if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3) > > + > > +@ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden > > +@ by the global definition in _arm_muldivsf3.o. This allows a program only > > +@ using multiplication to take the weak definition which does not contain the > > +@ division code. Programs using only division or both division and > > +@ multiplication will pull _arm_muldivsf3.o from which both the multiplication > > +@ and division are taken thanks to the override. > > +#ifdef L_arm_mulsf3 > > +WEAK mulsf3 > > +WEAK aeabi_fmul > > +#endif > > > > ARM_FUNC_START mulsf3 > > ARM_FUNC_ALIAS aeabi_fmul mulsf3 > > @@ -613,6 +624,8 @@ LSYM(Lml_n): > > FUNC_END aeabi_fmul > > FUNC_END mulsf3 > > > > +#ifdef L_arm_muldivsf3 > > + > > ARM_FUNC_START divsf3 > > ARM_FUNC_ALIAS aeabi_fdiv divsf3 > > CFI_START_FUNCTION > > @@ -756,6 +769,7 @@ LSYM(Ldv_s): > > FUNC_END divsf3 > > > > #endif /* L_muldivsf3 */ > > +#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */ > > > > #ifdef L_arm_cmpsf2 > > > > diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S > > index ff06d504a4c..193fb251fdb 100644 > > --- a/libgcc/config/arm/lib1funcs.S > > +++ b/libgcc/config/arm/lib1funcs.S > > @@ -359,12 +359,8 @@ SYM (\name): > > #define THUMB_SYNTAX > > #endif > > > > -.macro FUNC_START name sp_section= > > - .ifc \sp_section, function_section > > - .section .text.__\name,"ax",%progbits > > - .else > > +.macro FUNC_START name > > .text > > - .endif > > .globl SYM (__\name) > > TYPE (__\name) > > .align 0 > > @@ -390,8 +386,8 @@ SYM (\name): > > #if defined(__thumb2__) > > > > /* For Thumb-2 we build everything in thumb mode. */ > > -.macro ARM_FUNC_START name sp_section= > > - FUNC_START \name \sp_section > > +.macro ARM_FUNC_START name > > + FUNC_START \name > > .syntax unified > > .endm > > #define EQUIV .thumb_set > > @@ -422,12 +418,8 @@ _L__\name: > > #ifdef NOT_ISA_TARGET_32BIT > > #define EQUIV .thumb_set > > #else > > -.macro ARM_FUNC_START name sp_section= > > - .ifc \sp_section, function_section > > - .section .text.__\name,"ax",%progbits > > - .else > > +.macro ARM_FUNC_START name > > .text > > - .endif > > .globl SYM (__\name) > > TYPE (__\name) > > .align 0 > > @@ -2169,7 +2161,8 @@ LSYM(Lchange_\register): > > .endm > > > > #ifndef __symbian__ > > -/* The condition here must match the one in gcc/config/arm/elf.h. */ > > +/* The condition here must match the one in gcc/config/arm/elf.h and > > + libgcc/config/arm/t-elf. */ > > #ifndef NOT_ISA_TARGET_32BIT > > #include "ieee754-df.S" > > #include "ieee754-sf.S" > > diff --git a/libgcc/config/arm/t-elf b/libgcc/config/arm/t-elf > > index 9e7a3170f17..9da6cd37054 100644 > > --- a/libgcc/config/arm/t-elf > > +++ b/libgcc/config/arm/t-elf > > @@ -1,3 +1,19 @@ > > +ifeq (,$(findstring __symbian__,$(shell $(gcc_compile_bare) -dM -E - </dev/null))) > > + > > +ARM_ISA:=$(findstring __ARM_ARCH_ISA_ARM,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) > > +THUMB1_ISA:=$(findstring __ARM_ARCH_ISA_THUMB 1,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) > > + > > +# The condition here must match the one in gcc/config/arm/elf.h and > > +# libgcc/config/arm/lib1funcs.S. _arm_muldf3 and _arm_mulsf3 must be included > > +# first so that the weak multiplication symbols in the corresponding files are > > +# chosen over the global symbols that _arm_muldivdf3 and _arm_muldivsf3 > > +# inclusion create when only multiplication is used, thus avoiding pulling in > > +# useless division code. > > +ifneq (__ARM_ARCH_ISA_THUMB 1,$(ARM_ISA)$(THUMB1_ISA)) > > +LIB1ASMFUNCS += _arm_muldf3 _arm_mulsf3 > > +endif > > +endif # !__symbian__ > > + > > # For most CPUs we have an assembly soft-float implementations. > > # However this is not true for ARMv6M. Here we want to use the soft-fp C > > # implementation. The soft-fp code is only build for ARMv6M. This pulls > > >
On 14/12/2018 21:09, Thomas Preudhomme wrote: > Hi Richard, > > None, is there any? All the one I could find in the big switch > selecting tm_files and tmake_files in gcc/config.gcc are including > arm/elf.h. I tried to build for arm-wince-pe but got: "Configuration > arm-wince-pe not supported". However note that to guarantee correct > results the only requirement is to support global symbol overriding > weak symbol correctly and I see .weak usage in many other libgcc > backend (eg. i386). The "take the first definition resolving an > undefined reference and ignore the one in following object of a static > library" is only to benefit from the size optimization. > I'd forgotten that the last vestiges of all non-elf variants for Arm had been removed some time back. Never mind, then; clearly that can't be a concern... On the rest of the patch, this is OK. I'm not entirely sure that what you've done will reliably work in terms of guaranteeing to find the weak definition first within the same library, but at least it should be safe. R. > Best regards, > > Thomas > On Fri, 7 Dec 2018 at 14:14, Richard Earnshaw (lists) > <Richard.Earnshaw@arm.com> wrote: >> >> On 19/11/2018 09:57, Thomas Preudhomme wrote: >>> Softfloat single precision and double precision floating-point >>> multiplication routines in libgcc share some code with the >>> floating-point division of their corresponding precision. As the code >>> is structured now, this leads to *all* division code being pulled in an >>> executable in softfloat mode even if only multiplication is >>> performed. >>> >>> This patch create some new LIB1ASMFUNCS macros to also build files with >>> just the multiplication and shared code as weak symbols. By putting >>> these earlier in the static library, they can then be picked up when >>> only multiplication is used and they are overriden by the global >>> definition in the existing file containing both multiplication and >>> division code when division is needed. >>> >>> The patch also removes changes made to the FUNC_START and ARM_FUNC_START >>> macros in r218124 since the intent was to put multiplication and >>> division code into their own section in a later patch to achieve the >>> same size optimization. That approach relied on specific section layout >>> to ensure multiplication and division were not too far from the shared >>> bit of code in order to the branches to be within range. Due to lack of >>> guarantee regarding section layout, in particular with all the >>> possibility of linker scripts, this approach was chosen instead. This >>> patch keeps the two testcases that were posted by Tony Wang (an Arm >>> employee at the time) on the mailing list to implement this approach >>> and adds a new one, hence the attribution. >>> >>> ChangeLog entries are as follows: >>> >>> *** gcc/ChangeLog *** >>> >>> 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> >>> * config/arm/elf.h: Update comment about condition that need to >>> match with libgcc/config/arm/lib1funcs.S to also include >>> libgcc/config/arm/t-arm. >>> * doc/sourcebuild.texi (output-exists, output-exists-not): Rename >>> subsubsection these directives are in to "Check for output files". >>> Move scan-symbol to that section and add to it new scan-symbol-not >>> directive. >>> >>> *** gcc/testsuite/ChangeLog *** >>> >>> 2018-11-16 Tony Wang <tony.wang@arm.com> >>> Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> >>> * lib/lto.exp (lto-execute): Define output_file and testname_with_flags >>> to same value as execname. >>> (scan-symbol): Move and rename to ... >>> * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a >>> helper function returning true or false if a symbol is present. >>> (scan-symbol): New procedure. >>> (scan-symbol-not): Likewise. >>> * gcc.target/arm/size-optimization-ieee-1.c: New testcase. >>> * gcc.target/arm/size-optimization-ieee-2.c: Likewise. >>> * gcc.target/arm/size-optimization-ieee-3.c: Likewise. >>> >>> *** libgcc/ChangeLog *** >>> >>> 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> >>> * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section >>> parameter and corresponding code. >>> (ARM_FUNC_START): Likewise in both definitions. >>> Also update footer comment about condition that need to match with >>> gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. >>> * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is >>> defined. Weakly define it in this case. >>> * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. >>> * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and >>> _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add >>> comment to keep condition in sync with the one in >>> libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. >>> >>> Testing: Bootstrapped on arm-linux-gnueabihf (Arm & Thumb-2) and >>> testsuite shows no >>> regression. Also built an arm-none-eabi cross compiler targeting >>> soft-float which also shows no regression. In particular newly added >>> tests and gcc.dg/lto/20081212-1 test pass. >> >> Which non-elf targets have you tested? >> >> R. >> >>> >>> Is this ok for stage3? >>> >>> Best regards, >>> >>> Thomas >>> >>> >>> Optimize-size-fpmul_without_div.patch >>> >>> From 8740697791f99b7175e188f049663883c39e51b0 Mon Sep 17 00:00:00 2001 >>> From: Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> Date: Fri, 26 Oct 2018 16:21:09 +0100 >>> Subject: [PATCH] [PATCH, libgcc/ARM] Optimize executable size when using >>> softfloat fmul/dmul >>> >>> Softfloat single precision and double precision floating-point >>> multiplication routines in libgcc share some code with the >>> floating-point division of their corresponding precision. As the code >>> is structured now, this leads to *all* division code being pulled in an >>> executable in softfloat mode even if only multiplication is >>> performed. >>> >>> This patch create some new LIB1ASMFUNCS macros to also build files with >>> just the multiplication and shared code as weak symbols. By putting >>> these earlier in the static library, they can then be picked up when >>> only multiplication is used and they are overriden by the global >>> definition in the existing file containing both multiplication and >>> division code when division is needed. >>> >>> The patch also removes changes made to the FUNC_START and ARM_FUNC_START >>> macros in r218124 since the intent was to put multiplication and >>> division code into their own section in a later patch to achieve the >>> same size optimization. That approach relied on specific section layout >>> to ensure multiplication and division were not too far from the shared >>> bit of code in order to the branches to be within range. Due to lack of >>> guarantee regarding section layout, in particular with all the >>> possibility of linker scripts, this approach was chosen instead. This >>> patch keeps the two testcases that were posted by Tony Wang (an Arm >>> employee at the time) on the mailing list to implement this approach >>> and adds a new one, hence the attribution. >>> >>> ChangeLog entries are as follows: >>> >>> *** gcc/ChangeLog *** >>> >>> 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> >>> * config/arm/elf.h: Update comment about condition that need to >>> match with libgcc/config/arm/lib1funcs.S to also include >>> libgcc/config/arm/t-arm. >>> * doc/sourcebuild.texi (output-exists, output-exists-not): Rename >>> subsubsection these directives are in to "Check for output files". >>> Move scan-symbol to that section and add to it new scan-symbol-not >>> directive. >>> >>> *** gcc/testsuite/ChangeLog *** >>> >>> 2018-11-16 Tony Wang <tony.wang@arm.com> >>> Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> >>> * lib/lto.exp (lto-execute): Define output_file and testname_with_flags >>> to same value as execname. >>> (scan-symbol): Move and rename to ... >>> * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a >>> helper function returning true or false if a symbol is present. >>> (scan-symbol): New procedure. >>> (scan-symbol-not): Likewise. >>> * gcc.target/arm/size-optimization-ieee-1.c: New testcase. >>> * gcc.target/arm/size-optimization-ieee-2.c: Likewise. >>> * gcc.target/arm/size-optimization-ieee-3.c: Likewise. >>> >>> *** libgcc/ChangeLog *** >>> >>> 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> >>> >>> * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section >>> parameter and corresponding code. >>> (ARM_FUNC_START): Likewise in both definitions. >>> Also update footer comment about condition that need to match with >>> gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. >>> * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is >>> defined. Weakly define it in this case. >>> * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. >>> * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and >>> _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add >>> comment to keep condition in sync with the one in >>> libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. >>> >>> Testing: Bootstrapped on arm-linux-gnueabihf and testsuite shows no >>> regression. Also built an arm-none-eabi cross compiler targeting >>> soft-float which also shows no regression. In particular newly added >>> tests and gcc.dg/lto/20081212-1 test pass. >>> >>> Is this ok for stage3? >>> >>> Best regards, >>> >>> Thomas >>> --- >>> gcc/config/arm/elf.h | 2 +- >>> gcc/doc/sourcebuild.texi | 9 +-- >>> .../gcc.target/arm/size-optimization-ieee-1.c | 33 ++++++++ >>> .../gcc.target/arm/size-optimization-ieee-2.c | 31 ++++++++ >>> .../gcc.target/arm/size-optimization-ieee-3.c | 33 ++++++++ >>> gcc/testsuite/lib/gcc-dg.exp | 76 +++++++++++++++++++ >>> gcc/testsuite/lib/lto.exp | 63 +++------------ >>> libgcc/config/arm/ieee754-df.S | 17 ++++- >>> libgcc/config/arm/ieee754-sf.S | 16 +++- >>> libgcc/config/arm/lib1funcs.S | 19 ++--- >>> libgcc/config/arm/t-elf | 16 ++++ >>> 11 files changed, 243 insertions(+), 72 deletions(-) >>> create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c >>> create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c >>> create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c >>> >>> diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h >>> index ad3651ba841..1e00e99afc6 100644 >>> --- a/gcc/config/arm/elf.h >>> +++ b/gcc/config/arm/elf.h >>> @@ -137,7 +137,7 @@ >>> >>> /* Horrible hack: We want to prevent some libgcc routines being included >>> for some multilibs. The condition should match the one in >>> - libgcc/config/arm/lib1funcs.S. */ >>> + libgcc/config/arm/lib1funcs.S and libgcc/config/arm/t-elf. */ >>> #if __ARM_ARCH_ISA_ARM || __ARM_ARCH_ISA_THUMB != 1 >>> #undef L_fixdfsi >>> #undef L_fixunsdfsi >>> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi >>> index 89157079ffb..9bf59b81d87 100644 >>> --- a/gcc/doc/sourcebuild.texi >>> +++ b/gcc/doc/sourcebuild.texi >>> @@ -2638,7 +2638,7 @@ Passes if @var{regex} does not match demangled text in the dump file with >>> suffix @var{suffix}. >>> @end table >>> >>> -@subsubsection Verify that an output files exists or not >>> +@subsubsection Check for output files >>> >>> @table @code >>> @item output-exists [@{ target/xfail @var{selector} @}] >>> @@ -2646,13 +2646,12 @@ Passes if compiler output file exists. >>> >>> @item output-exists-not [@{ target/xfail @var{selector} @}] >>> Passes if compiler output file does not exist. >>> -@end table >>> - >>> -@subsubsection Check for LTO tests >>> >>> -@table @code >>> @item scan-symbol @var{regexp} [@{ target/xfail @var{selector} @}] >>> Passes if the pattern is present in the final executable. >>> + >>> +@item scan-symbol-not @var{regexp} [@{ target/xfail @var{selector} @}] >>> +Passes if the pattern is absent from the final executable. >>> @end table >>> >>> @subsubsection Checks for @command{gcov} tests >>> diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c >>> new file mode 100644 >>> index 00000000000..34090f20fec >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do link { target arm_soft_ok } } */ >>> +/* { dg-options "-mfloat-abi=soft" } */ >>> + >>> +int >>> +foo (void) >>> +{ >>> + volatile float a; >>> + volatile float b; >>> + volatile float c = a * b; >>> + return 0; >>> +} >>> + >>> +int >>> +bar (void) >>> +{ >>> + volatile double a; >>> + volatile double b; >>> + volatile double c = a * b; >>> + return 0; >>> +} >>> + >>> +int >>> +main (void) >>> +{ >>> + foo (); >>> + bar (); >>> + return 0; >>> +} >>> + >>> +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ >>> +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ >>> +/* { dg-final { scan-symbol-not "__aeabi_fdiv" } } */ >>> +/* { dg-final { scan-symbol-not "__aeabi_ddiv" } } */ >>> diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c >>> new file mode 100644 >>> index 00000000000..75337894a9c >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c >>> @@ -0,0 +1,31 @@ >>> +/* { dg-do link { target arm_soft_ok } } */ >>> +/* { dg-options "-mfloat-abi=soft" } */ >>> + >>> +int >>> +foo (void) >>> +{ >>> + volatile float a; >>> + volatile float b; >>> + volatile float c = a / b; >>> + return 0; >>> +} >>> + >>> +int >>> +bar (void) >>> +{ >>> + volatile double a; >>> + volatile double b; >>> + volatile double c = a / b; >>> + return 0; >>> +} >>> + >>> +int >>> +main (void) >>> +{ >>> + foo (); >>> + bar (); >>> + return 0; >>> +} >>> + >>> +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ >>> +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ >>> diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c >>> new file mode 100644 >>> index 00000000000..63c92b3bbb7 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do link { target arm_soft_ok } } */ >>> +/* { dg-options "-mfloat-abi=soft" } */ >>> + >>> +int >>> +foo (void) >>> +{ >>> + volatile float a; >>> + volatile float b; >>> + volatile float c = a * b + a / b; >>> + return 0; >>> +} >>> + >>> +int >>> +bar (void) >>> +{ >>> + volatile double a; >>> + volatile double b; >>> + volatile double c = a * b + a / b; >>> + return 0; >>> +} >>> + >>> +int >>> +main (void) >>> +{ >>> + foo (); >>> + bar (); >>> + return 0; >>> +} >>> + >>> +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ >>> +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ >>> +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ >>> +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ >>> diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp >>> index c33a50c0b13..0472b63f94c 100644 >>> --- a/gcc/testsuite/lib/gcc-dg.exp >>> +++ b/gcc/testsuite/lib/gcc-dg.exp >>> @@ -1236,5 +1236,81 @@ proc gdb-exists { args } { >>> return 0; >>> } >>> >>> +# Helper function for scan-symbol and scan-symbol-not. It scans a symbol in >>> +# the final executable and return 1 if present, otherwise fail. >>> +# >>> +# Argument 0 is the regexp to match. >>> +# Argument 1 handles expected failures and the like >>> +proc scan-symbol-common { scan_directive args } { >>> + global nm >>> + global base_dir >>> + >>> + # Access variable from gcc-dg-test-1 or lto-execute. >>> + upvar 3 output_file output_file >>> + >>> + if { [llength $args] >= 2 } { >>> + switch [dg-process-target [lindex $args 1]] { >>> + "S" { } >>> + "N" { return } >>> + "F" { setup_xfail "*-*-*" } >>> + "P" { } >>> + } >>> + } >>> + >>> + # Find nm like we find g++ in g++.exp. >>> + if ![info exists nm] { >>> + set nm [findfile $base_dir/../../../binutils/nm \ >>> + $base_dir/../../../binutils/nm \ >>> + [findfile $base_dir/../../nm $base_dir/../../nm \ >>> + [findfile $base_dir/nm $base_dir/nm \ >>> + [transform nm]]]] >>> + verbose -log "nm is $nm" >>> + } >>> + >>> + set output_file "[glob -nocomplain $output_file]" >>> + if { $output_file == "" } { >>> + fail "$scan_directive $args: output file does not exist" >>> + return >>> + } >>> + >>> + set fd [open "| $nm $output_file" r] >>> + set text [read $fd] >>> + close $fd >>> + >>> + if [regexp -- [lindex $args 0] $text] { >>> + return 1 >>> + } else { >>> + return 0 >>> + } >>> +} >>> + >>> +# Utility for scanning a symbol in the final executable, invoked via dg-final. >>> +# Call pass if pattern is present, otherwise fail. >>> +# >>> +# Argument 0 is the regexp to match. >>> +# Argument 1 handles expected failures and the like >>> +proc scan-symbol { args } { >>> + set testcase [testname-for-summary] >>> + if { [scan-symbol-common "scan-symbol" $args]} { >>> + pass "$testcase scan-symbol $args" >>> + } else { >>> + fail "$testcase scan-symbol $args" >>> + } >>> +} >>> + >>> +# Utility for scanning a symbol in the final executable, invoked via dg-final. >>> +# Call pass if pattern is absent, otherwise fail. >>> +# >>> +# Argument 0 is the regexp to match. >>> +# Argument 1 handles expected failures and the like >>> +proc scan-symbol-not { args } { >>> + set testcase [testname-for-summary] >>> + if { [scan-symbol-common "scan-symbol-not" $args]} { >>> + fail "$testcase scan-symbol-not $args" >>> + } else { >>> + pass "$testcase scan-symbol-not $args" >>> + } >>> +} >>> + >>> set additional_prunes "" >>> set dg_runtest_extra_prunes "" >>> diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp >>> index 58a84aa1936..c2c35698827 100644 >>> --- a/gcc/testsuite/lib/lto.exp >>> +++ b/gcc/testsuite/lib/lto.exp >>> @@ -712,6 +712,17 @@ proc lto-execute { src1 sid } { >>> >>> # There's a unique name for each executable we generate. >>> set execname "${execbase}-${count}1.exe" >>> + >>> + # The LTO tests don't use dg-test, so testname_with_flags and >>> + # output_file need to be defined explicitly for each file. scan-symbol >>> + # directives rely on both of these to be defined to find the symbol to >>> + # scan and for the text to print in the PASS/FAIL since they can also >>> + # be called from dg-test. testname_with_flags is also used via >>> + # testname-for-summary when calling into generic function below to >>> + # clean temporary files. >>> + set output_file $execname >>> + set testname_with_flags $execname >>> + >>> incr count >>> >>> file_on_host delete $execname >>> @@ -774,11 +785,7 @@ proc lto-execute { src1 sid } { >>> } >>> } >>> >>> - # Clean up after -save-temps. The LTO tests don't use dg-test, so >>> - # testname-for-summary needs to be defined explicitly for each >>> - # file that needs to be removed. >>> - set testname_with_flags $execname >>> - >>> + # Clean up after -save-temps. >>> eval "cleanup-saved-temps" >>> >>> for {set i 0} {$i < $num_srcs} {incr i} { >>> @@ -801,52 +808,6 @@ proc lto-execute { src1 sid } { >>> } >>> } >>> >>> -# Utility for scanning a symbol in the final executable, invoked via dg-final. >>> -# Call pass if pattern is present, otherwise fail. >>> -# >>> -# Argument 0 is the regexp to match. >>> -# Argument 1 handles expected failures and the like >>> -proc scan-symbol { args } { >>> - global nm >>> - global base_dir >>> - upvar 2 execname execname >>> - >>> - if { [llength $args] >= 2 } { >>> - switch [dg-process-target [lindex $args 1]] { >>> - "S" { } >>> - "N" { return } >>> - "F" { setup_xfail "*-*-*" } >>> - "P" { } >>> - } >>> - } >>> - >>> - # Find nm like we find g++ in g++.exp. >>> - if ![info exists nm] { >>> - set nm [findfile $base_dir/../../../binutils/nm \ >>> - $base_dir/../../../binutils/nm \ >>> - [findfile $base_dir/../../nm $base_dir/../../nm \ >>> - [findfile $base_dir/nm $base_dir/nm \ >>> - [transform nm]]]] >>> - verbose -log "nm is $nm" >>> - } >>> - >>> - set output_file "[glob -nocomplain $execname]" >>> - if { $output_file == "" } { >>> - fail "scan-symbol $args: dump file does not exist" >>> - return >>> - } >>> - >>> - set fd [open "| $nm $output_file" r] >>> - set text [read $fd] >>> - close $fd >>> - >>> - if [regexp -- [lindex $args 0] $text] { >>> - pass "scan-symbol $args" >>> - } else { >>> - fail "scan-symbol $args" >>> - } >>> -} >>> - >>> # Call pass if object readelf is ok, otherwise fail. >>> # example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */ >>> proc object-readelf { args } { >>> diff --git a/libgcc/config/arm/ieee754-df.S b/libgcc/config/arm/ieee754-df.S >>> index 480e33da31f..9f2ae9ed698 100644 >>> --- a/libgcc/config/arm/ieee754-df.S >>> +++ b/libgcc/config/arm/ieee754-df.S >>> @@ -617,7 +617,18 @@ ARM_FUNC_ALIAS aeabi_l2d floatdidf >>> >>> #endif /* L_addsubdf3 */ >>> >>> -#ifdef L_arm_muldivdf3 >>> +#if defined(L_arm_muldf3) || defined(L_arm_muldivdf3) >>> + >>> +@ Define multiplication as weak in _arm_muldf3.o so that it can be overriden >>> +@ by the global definition in _arm_muldivdf3.o. This allows a program only >>> +@ using multiplication to take the weak definition which does not contain the >>> +@ division code. Programs using only division or both division and >>> +@ multiplication will pull _arm_muldivdf3.o from which both the multiplication >>> +@ and division are taken thanks to the override. >>> +#ifdef L_arm_muldf3 >>> +WEAK muldf3 >>> +WEAK aeabi_dmul >>> +#endif >>> >>> ARM_FUNC_START muldf3 >>> ARM_FUNC_ALIAS aeabi_dmul muldf3 >>> @@ -719,6 +730,7 @@ LSYM(Lml_1): >>> orr xh, xh, #0x00100000 >>> mov lr, #0 >>> subs r4, r4, #1 >>> + >>> LSYM(Lml_u): >>> @ Overflow? >>> bgt LSYM(Lml_o) >>> @@ -870,6 +882,8 @@ LSYM(Lml_n): >>> FUNC_END aeabi_dmul >>> FUNC_END muldf3 >>> >>> +#ifdef L_arm_muldivdf3 >>> + >>> ARM_FUNC_START divdf3 >>> ARM_FUNC_ALIAS aeabi_ddiv divdf3 >>> CFI_START_FUNCTION >>> @@ -1067,6 +1081,7 @@ LSYM(Ldv_s): >>> FUNC_END divdf3 >>> >>> #endif /* L_muldivdf3 */ >>> +#endif /* L_arm_muldf3 || L_arm_muldivdf3 */ >>> >>> #ifdef L_arm_cmpdf2 >>> >>> diff --git a/libgcc/config/arm/ieee754-sf.S b/libgcc/config/arm/ieee754-sf.S >>> index 28e0d793281..0b4d1ab377d 100644 >>> --- a/libgcc/config/arm/ieee754-sf.S >>> +++ b/libgcc/config/arm/ieee754-sf.S >>> @@ -428,7 +428,18 @@ ARM_FUNC_ALIAS aeabi_l2f floatdisf >>> >>> #endif /* L_addsubsf3 */ >>> >>> -#ifdef L_arm_muldivsf3 >>> +#if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3) >>> + >>> +@ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden >>> +@ by the global definition in _arm_muldivsf3.o. This allows a program only >>> +@ using multiplication to take the weak definition which does not contain the >>> +@ division code. Programs using only division or both division and >>> +@ multiplication will pull _arm_muldivsf3.o from which both the multiplication >>> +@ and division are taken thanks to the override. >>> +#ifdef L_arm_mulsf3 >>> +WEAK mulsf3 >>> +WEAK aeabi_fmul >>> +#endif >>> >>> ARM_FUNC_START mulsf3 >>> ARM_FUNC_ALIAS aeabi_fmul mulsf3 >>> @@ -613,6 +624,8 @@ LSYM(Lml_n): >>> FUNC_END aeabi_fmul >>> FUNC_END mulsf3 >>> >>> +#ifdef L_arm_muldivsf3 >>> + >>> ARM_FUNC_START divsf3 >>> ARM_FUNC_ALIAS aeabi_fdiv divsf3 >>> CFI_START_FUNCTION >>> @@ -756,6 +769,7 @@ LSYM(Ldv_s): >>> FUNC_END divsf3 >>> >>> #endif /* L_muldivsf3 */ >>> +#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */ >>> >>> #ifdef L_arm_cmpsf2 >>> >>> diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S >>> index ff06d504a4c..193fb251fdb 100644 >>> --- a/libgcc/config/arm/lib1funcs.S >>> +++ b/libgcc/config/arm/lib1funcs.S >>> @@ -359,12 +359,8 @@ SYM (\name): >>> #define THUMB_SYNTAX >>> #endif >>> >>> -.macro FUNC_START name sp_section= >>> - .ifc \sp_section, function_section >>> - .section .text.__\name,"ax",%progbits >>> - .else >>> +.macro FUNC_START name >>> .text >>> - .endif >>> .globl SYM (__\name) >>> TYPE (__\name) >>> .align 0 >>> @@ -390,8 +386,8 @@ SYM (\name): >>> #if defined(__thumb2__) >>> >>> /* For Thumb-2 we build everything in thumb mode. */ >>> -.macro ARM_FUNC_START name sp_section= >>> - FUNC_START \name \sp_section >>> +.macro ARM_FUNC_START name >>> + FUNC_START \name >>> .syntax unified >>> .endm >>> #define EQUIV .thumb_set >>> @@ -422,12 +418,8 @@ _L__\name: >>> #ifdef NOT_ISA_TARGET_32BIT >>> #define EQUIV .thumb_set >>> #else >>> -.macro ARM_FUNC_START name sp_section= >>> - .ifc \sp_section, function_section >>> - .section .text.__\name,"ax",%progbits >>> - .else >>> +.macro ARM_FUNC_START name >>> .text >>> - .endif >>> .globl SYM (__\name) >>> TYPE (__\name) >>> .align 0 >>> @@ -2169,7 +2161,8 @@ LSYM(Lchange_\register): >>> .endm >>> >>> #ifndef __symbian__ >>> -/* The condition here must match the one in gcc/config/arm/elf.h. */ >>> +/* The condition here must match the one in gcc/config/arm/elf.h and >>> + libgcc/config/arm/t-elf. */ >>> #ifndef NOT_ISA_TARGET_32BIT >>> #include "ieee754-df.S" >>> #include "ieee754-sf.S" >>> diff --git a/libgcc/config/arm/t-elf b/libgcc/config/arm/t-elf >>> index 9e7a3170f17..9da6cd37054 100644 >>> --- a/libgcc/config/arm/t-elf >>> +++ b/libgcc/config/arm/t-elf >>> @@ -1,3 +1,19 @@ >>> +ifeq (,$(findstring __symbian__,$(shell $(gcc_compile_bare) -dM -E - </dev/null))) >>> + >>> +ARM_ISA:=$(findstring __ARM_ARCH_ISA_ARM,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) >>> +THUMB1_ISA:=$(findstring __ARM_ARCH_ISA_THUMB 1,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) >>> + >>> +# The condition here must match the one in gcc/config/arm/elf.h and >>> +# libgcc/config/arm/lib1funcs.S. _arm_muldf3 and _arm_mulsf3 must be included >>> +# first so that the weak multiplication symbols in the corresponding files are >>> +# chosen over the global symbols that _arm_muldivdf3 and _arm_muldivsf3 >>> +# inclusion create when only multiplication is used, thus avoiding pulling in >>> +# useless division code. >>> +ifneq (__ARM_ARCH_ISA_THUMB 1,$(ARM_ISA)$(THUMB1_ISA)) >>> +LIB1ASMFUNCS += _arm_muldf3 _arm_mulsf3 >>> +endif >>> +endif # !__symbian__ >>> + >>> # For most CPUs we have an assembly soft-float implementations. >>> # However this is not true for ARMv6M. Here we want to use the soft-fp C >>> # implementation. The soft-fp code is only build for ARMv6M. This pulls >>> >>
From 8740697791f99b7175e188f049663883c39e51b0 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme <thomas.preudhomme@linaro.org> Date: Fri, 26 Oct 2018 16:21:09 +0100 Subject: [PATCH] [PATCH, libgcc/ARM] Optimize executable size when using softfloat fmul/dmul Softfloat single precision and double precision floating-point multiplication routines in libgcc share some code with the floating-point division of their corresponding precision. As the code is structured now, this leads to *all* division code being pulled in an executable in softfloat mode even if only multiplication is performed. This patch create some new LIB1ASMFUNCS macros to also build files with just the multiplication and shared code as weak symbols. By putting these earlier in the static library, they can then be picked up when only multiplication is used and they are overriden by the global definition in the existing file containing both multiplication and division code when division is needed. The patch also removes changes made to the FUNC_START and ARM_FUNC_START macros in r218124 since the intent was to put multiplication and division code into their own section in a later patch to achieve the same size optimization. That approach relied on specific section layout to ensure multiplication and division were not too far from the shared bit of code in order to the branches to be within range. Due to lack of guarantee regarding section layout, in particular with all the possibility of linker scripts, this approach was chosen instead. This patch keeps the two testcases that were posted by Tony Wang (an Arm employee at the time) on the mailing list to implement this approach and adds a new one, hence the attribution. ChangeLog entries are as follows: *** gcc/ChangeLog *** 2018-11-14 Thomas Preud'homme <thomas.preudhomme@linaro.org> * config/arm/elf.h: Update comment about condition that need to match with libgcc/config/arm/lib1funcs.S to also include libgcc/config/arm/t-arm. * doc/sourcebuild.texi (output-exists, output-exists-not): Rename subsubsection these directives are in to "Check for output files". Move scan-symbol to that section and add to it new scan-symbol-not directive. *** gcc/testsuite/ChangeLog *** 2018-11-16 Tony Wang <tony.wang@arm.com> Thomas Preud'homme <thomas.preudhomme@linaro.org> * lib/lto.exp (lto-execute): Define output_file and testname_with_flags to same value as execname. (scan-symbol): Move and rename to ... * lib/gcc-dg.exp (scan-symbol-common): This. Adapt into a helper function returning true or false if a symbol is present. (scan-symbol): New procedure. (scan-symbol-not): Likewise. * gcc.target/arm/size-optimization-ieee-1.c: New testcase. * gcc.target/arm/size-optimization-ieee-2.c: Likewise. * gcc.target/arm/size-optimization-ieee-3.c: Likewise. *** libgcc/ChangeLog *** 2018-11-16 Thomas Preud'homme <thomas.preudhomme@linaro.org> * /config/arm/lib1funcs.S (FUNC_START): Remove unused sp_section parameter and corresponding code. (ARM_FUNC_START): Likewise in both definitions. Also update footer comment about condition that need to match with gcc/config/arm/elf.h to also include libgcc/config/arm/t-arm. * config/arm/ieee754-df.S (muldf3): Also build it if L_arm_muldf3 is defined. Weakly define it in this case. * config/arm/ieee754-sf.S (mulsf3): Likewise with L_arm_mulsf3. * config/arm/t-elf (LIB1ASMFUNCS): Build _arm_muldf3.o and _arm_mulsf3.o before muldiv versions if targeting Thumb-1 only. Add comment to keep condition in sync with the one in libgcc/config/arm/lib1funcs.S and gcc/config/arm/elf.h. Testing: Bootstrapped on arm-linux-gnueabihf and testsuite shows no regression. Also built an arm-none-eabi cross compiler targeting soft-float which also shows no regression. In particular newly added tests and gcc.dg/lto/20081212-1 test pass. Is this ok for stage3? Best regards, Thomas --- gcc/config/arm/elf.h | 2 +- gcc/doc/sourcebuild.texi | 9 +-- .../gcc.target/arm/size-optimization-ieee-1.c | 33 ++++++++ .../gcc.target/arm/size-optimization-ieee-2.c | 31 ++++++++ .../gcc.target/arm/size-optimization-ieee-3.c | 33 ++++++++ gcc/testsuite/lib/gcc-dg.exp | 76 +++++++++++++++++++ gcc/testsuite/lib/lto.exp | 63 +++------------ libgcc/config/arm/ieee754-df.S | 17 ++++- libgcc/config/arm/ieee754-sf.S | 16 +++- libgcc/config/arm/lib1funcs.S | 19 ++--- libgcc/config/arm/t-elf | 16 ++++ 11 files changed, 243 insertions(+), 72 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c create mode 100644 gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h index ad3651ba841..1e00e99afc6 100644 --- a/gcc/config/arm/elf.h +++ b/gcc/config/arm/elf.h @@ -137,7 +137,7 @@ /* Horrible hack: We want to prevent some libgcc routines being included for some multilibs. The condition should match the one in - libgcc/config/arm/lib1funcs.S. */ + libgcc/config/arm/lib1funcs.S and libgcc/config/arm/t-elf. */ #if __ARM_ARCH_ISA_ARM || __ARM_ARCH_ISA_THUMB != 1 #undef L_fixdfsi #undef L_fixunsdfsi diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 89157079ffb..9bf59b81d87 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2638,7 +2638,7 @@ Passes if @var{regex} does not match demangled text in the dump file with suffix @var{suffix}. @end table -@subsubsection Verify that an output files exists or not +@subsubsection Check for output files @table @code @item output-exists [@{ target/xfail @var{selector} @}] @@ -2646,13 +2646,12 @@ Passes if compiler output file exists. @item output-exists-not [@{ target/xfail @var{selector} @}] Passes if compiler output file does not exist. -@end table - -@subsubsection Check for LTO tests -@table @code @item scan-symbol @var{regexp} [@{ target/xfail @var{selector} @}] Passes if the pattern is present in the final executable. + +@item scan-symbol-not @var{regexp} [@{ target/xfail @var{selector} @}] +Passes if the pattern is absent from the final executable. @end table @subsubsection Checks for @command{gcov} tests diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c new file mode 100644 index 00000000000..34090f20fec --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-1.c @@ -0,0 +1,33 @@ +/* { dg-do link { target arm_soft_ok } } */ +/* { dg-options "-mfloat-abi=soft" } */ + +int +foo (void) +{ + volatile float a; + volatile float b; + volatile float c = a * b; + return 0; +} + +int +bar (void) +{ + volatile double a; + volatile double b; + volatile double c = a * b; + return 0; +} + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ +/* { dg-final { scan-symbol-not "__aeabi_fdiv" } } */ +/* { dg-final { scan-symbol-not "__aeabi_ddiv" } } */ diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c new file mode 100644 index 00000000000..75337894a9c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-2.c @@ -0,0 +1,31 @@ +/* { dg-do link { target arm_soft_ok } } */ +/* { dg-options "-mfloat-abi=soft" } */ + +int +foo (void) +{ + volatile float a; + volatile float b; + volatile float c = a / b; + return 0; +} + +int +bar (void) +{ + volatile double a; + volatile double b; + volatile double c = a / b; + return 0; +} + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ diff --git a/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c new file mode 100644 index 00000000000..63c92b3bbb7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/size-optimization-ieee-3.c @@ -0,0 +1,33 @@ +/* { dg-do link { target arm_soft_ok } } */ +/* { dg-options "-mfloat-abi=soft" } */ + +int +foo (void) +{ + volatile float a; + volatile float b; + volatile float c = a * b + a / b; + return 0; +} + +int +bar (void) +{ + volatile double a; + volatile double b; + volatile double c = a * b + a / b; + return 0; +} + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +/* { dg-final { scan-symbol "__aeabi_fmul" } } */ +/* { dg-final { scan-symbol "__aeabi_dmul" } } */ +/* { dg-final { scan-symbol "__aeabi_fdiv" } } */ +/* { dg-final { scan-symbol "__aeabi_ddiv" } } */ diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index c33a50c0b13..0472b63f94c 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -1236,5 +1236,81 @@ proc gdb-exists { args } { return 0; } +# Helper function for scan-symbol and scan-symbol-not. It scans a symbol in +# the final executable and return 1 if present, otherwise fail. +# +# Argument 0 is the regexp to match. +# Argument 1 handles expected failures and the like +proc scan-symbol-common { scan_directive args } { + global nm + global base_dir + + # Access variable from gcc-dg-test-1 or lto-execute. + upvar 3 output_file output_file + + if { [llength $args] >= 2 } { + switch [dg-process-target [lindex $args 1]] { + "S" { } + "N" { return } + "F" { setup_xfail "*-*-*" } + "P" { } + } + } + + # Find nm like we find g++ in g++.exp. + if ![info exists nm] { + set nm [findfile $base_dir/../../../binutils/nm \ + $base_dir/../../../binutils/nm \ + [findfile $base_dir/../../nm $base_dir/../../nm \ + [findfile $base_dir/nm $base_dir/nm \ + [transform nm]]]] + verbose -log "nm is $nm" + } + + set output_file "[glob -nocomplain $output_file]" + if { $output_file == "" } { + fail "$scan_directive $args: output file does not exist" + return + } + + set fd [open "| $nm $output_file" r] + set text [read $fd] + close $fd + + if [regexp -- [lindex $args 0] $text] { + return 1 + } else { + return 0 + } +} + +# Utility for scanning a symbol in the final executable, invoked via dg-final. +# Call pass if pattern is present, otherwise fail. +# +# Argument 0 is the regexp to match. +# Argument 1 handles expected failures and the like +proc scan-symbol { args } { + set testcase [testname-for-summary] + if { [scan-symbol-common "scan-symbol" $args]} { + pass "$testcase scan-symbol $args" + } else { + fail "$testcase scan-symbol $args" + } +} + +# Utility for scanning a symbol in the final executable, invoked via dg-final. +# Call pass if pattern is absent, otherwise fail. +# +# Argument 0 is the regexp to match. +# Argument 1 handles expected failures and the like +proc scan-symbol-not { args } { + set testcase [testname-for-summary] + if { [scan-symbol-common "scan-symbol-not" $args]} { + fail "$testcase scan-symbol-not $args" + } else { + pass "$testcase scan-symbol-not $args" + } +} + set additional_prunes "" set dg_runtest_extra_prunes "" diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp index 58a84aa1936..c2c35698827 100644 --- a/gcc/testsuite/lib/lto.exp +++ b/gcc/testsuite/lib/lto.exp @@ -712,6 +712,17 @@ proc lto-execute { src1 sid } { # There's a unique name for each executable we generate. set execname "${execbase}-${count}1.exe" + + # The LTO tests don't use dg-test, so testname_with_flags and + # output_file need to be defined explicitly for each file. scan-symbol + # directives rely on both of these to be defined to find the symbol to + # scan and for the text to print in the PASS/FAIL since they can also + # be called from dg-test. testname_with_flags is also used via + # testname-for-summary when calling into generic function below to + # clean temporary files. + set output_file $execname + set testname_with_flags $execname + incr count file_on_host delete $execname @@ -774,11 +785,7 @@ proc lto-execute { src1 sid } { } } - # Clean up after -save-temps. The LTO tests don't use dg-test, so - # testname-for-summary needs to be defined explicitly for each - # file that needs to be removed. - set testname_with_flags $execname - + # Clean up after -save-temps. eval "cleanup-saved-temps" for {set i 0} {$i < $num_srcs} {incr i} { @@ -801,52 +808,6 @@ proc lto-execute { src1 sid } { } } -# Utility for scanning a symbol in the final executable, invoked via dg-final. -# Call pass if pattern is present, otherwise fail. -# -# Argument 0 is the regexp to match. -# Argument 1 handles expected failures and the like -proc scan-symbol { args } { - global nm - global base_dir - upvar 2 execname execname - - if { [llength $args] >= 2 } { - switch [dg-process-target [lindex $args 1]] { - "S" { } - "N" { return } - "F" { setup_xfail "*-*-*" } - "P" { } - } - } - - # Find nm like we find g++ in g++.exp. - if ![info exists nm] { - set nm [findfile $base_dir/../../../binutils/nm \ - $base_dir/../../../binutils/nm \ - [findfile $base_dir/../../nm $base_dir/../../nm \ - [findfile $base_dir/nm $base_dir/nm \ - [transform nm]]]] - verbose -log "nm is $nm" - } - - set output_file "[glob -nocomplain $execname]" - if { $output_file == "" } { - fail "scan-symbol $args: dump file does not exist" - return - } - - set fd [open "| $nm $output_file" r] - set text [read $fd] - close $fd - - if [regexp -- [lindex $args 0] $text] { - pass "scan-symbol $args" - } else { - fail "scan-symbol $args" - } -} - # Call pass if object readelf is ok, otherwise fail. # example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */ proc object-readelf { args } { diff --git a/libgcc/config/arm/ieee754-df.S b/libgcc/config/arm/ieee754-df.S index 480e33da31f..9f2ae9ed698 100644 --- a/libgcc/config/arm/ieee754-df.S +++ b/libgcc/config/arm/ieee754-df.S @@ -617,7 +617,18 @@ ARM_FUNC_ALIAS aeabi_l2d floatdidf #endif /* L_addsubdf3 */ -#ifdef L_arm_muldivdf3 +#if defined(L_arm_muldf3) || defined(L_arm_muldivdf3) + +@ Define multiplication as weak in _arm_muldf3.o so that it can be overriden +@ by the global definition in _arm_muldivdf3.o. This allows a program only +@ using multiplication to take the weak definition which does not contain the +@ division code. Programs using only division or both division and +@ multiplication will pull _arm_muldivdf3.o from which both the multiplication +@ and division are taken thanks to the override. +#ifdef L_arm_muldf3 +WEAK muldf3 +WEAK aeabi_dmul +#endif ARM_FUNC_START muldf3 ARM_FUNC_ALIAS aeabi_dmul muldf3 @@ -719,6 +730,7 @@ LSYM(Lml_1): orr xh, xh, #0x00100000 mov lr, #0 subs r4, r4, #1 + LSYM(Lml_u): @ Overflow? bgt LSYM(Lml_o) @@ -870,6 +882,8 @@ LSYM(Lml_n): FUNC_END aeabi_dmul FUNC_END muldf3 +#ifdef L_arm_muldivdf3 + ARM_FUNC_START divdf3 ARM_FUNC_ALIAS aeabi_ddiv divdf3 CFI_START_FUNCTION @@ -1067,6 +1081,7 @@ LSYM(Ldv_s): FUNC_END divdf3 #endif /* L_muldivdf3 */ +#endif /* L_arm_muldf3 || L_arm_muldivdf3 */ #ifdef L_arm_cmpdf2 diff --git a/libgcc/config/arm/ieee754-sf.S b/libgcc/config/arm/ieee754-sf.S index 28e0d793281..0b4d1ab377d 100644 --- a/libgcc/config/arm/ieee754-sf.S +++ b/libgcc/config/arm/ieee754-sf.S @@ -428,7 +428,18 @@ ARM_FUNC_ALIAS aeabi_l2f floatdisf #endif /* L_addsubsf3 */ -#ifdef L_arm_muldivsf3 +#if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3) + +@ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden +@ by the global definition in _arm_muldivsf3.o. This allows a program only +@ using multiplication to take the weak definition which does not contain the +@ division code. Programs using only division or both division and +@ multiplication will pull _arm_muldivsf3.o from which both the multiplication +@ and division are taken thanks to the override. +#ifdef L_arm_mulsf3 +WEAK mulsf3 +WEAK aeabi_fmul +#endif ARM_FUNC_START mulsf3 ARM_FUNC_ALIAS aeabi_fmul mulsf3 @@ -613,6 +624,8 @@ LSYM(Lml_n): FUNC_END aeabi_fmul FUNC_END mulsf3 +#ifdef L_arm_muldivsf3 + ARM_FUNC_START divsf3 ARM_FUNC_ALIAS aeabi_fdiv divsf3 CFI_START_FUNCTION @@ -756,6 +769,7 @@ LSYM(Ldv_s): FUNC_END divsf3 #endif /* L_muldivsf3 */ +#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */ #ifdef L_arm_cmpsf2 diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S index ff06d504a4c..193fb251fdb 100644 --- a/libgcc/config/arm/lib1funcs.S +++ b/libgcc/config/arm/lib1funcs.S @@ -359,12 +359,8 @@ SYM (\name): #define THUMB_SYNTAX #endif -.macro FUNC_START name sp_section= - .ifc \sp_section, function_section - .section .text.__\name,"ax",%progbits - .else +.macro FUNC_START name .text - .endif .globl SYM (__\name) TYPE (__\name) .align 0 @@ -390,8 +386,8 @@ SYM (\name): #if defined(__thumb2__) /* For Thumb-2 we build everything in thumb mode. */ -.macro ARM_FUNC_START name sp_section= - FUNC_START \name \sp_section +.macro ARM_FUNC_START name + FUNC_START \name .syntax unified .endm #define EQUIV .thumb_set @@ -422,12 +418,8 @@ _L__\name: #ifdef NOT_ISA_TARGET_32BIT #define EQUIV .thumb_set #else -.macro ARM_FUNC_START name sp_section= - .ifc \sp_section, function_section - .section .text.__\name,"ax",%progbits - .else +.macro ARM_FUNC_START name .text - .endif .globl SYM (__\name) TYPE (__\name) .align 0 @@ -2169,7 +2161,8 @@ LSYM(Lchange_\register): .endm #ifndef __symbian__ -/* The condition here must match the one in gcc/config/arm/elf.h. */ +/* The condition here must match the one in gcc/config/arm/elf.h and + libgcc/config/arm/t-elf. */ #ifndef NOT_ISA_TARGET_32BIT #include "ieee754-df.S" #include "ieee754-sf.S" diff --git a/libgcc/config/arm/t-elf b/libgcc/config/arm/t-elf index 9e7a3170f17..9da6cd37054 100644 --- a/libgcc/config/arm/t-elf +++ b/libgcc/config/arm/t-elf @@ -1,3 +1,19 @@ +ifeq (,$(findstring __symbian__,$(shell $(gcc_compile_bare) -dM -E - </dev/null))) + +ARM_ISA:=$(findstring __ARM_ARCH_ISA_ARM,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) +THUMB1_ISA:=$(findstring __ARM_ARCH_ISA_THUMB 1,$(shell $(gcc_compile_bare) -dM -E - </dev/null)) + +# The condition here must match the one in gcc/config/arm/elf.h and +# libgcc/config/arm/lib1funcs.S. _arm_muldf3 and _arm_mulsf3 must be included +# first so that the weak multiplication symbols in the corresponding files are +# chosen over the global symbols that _arm_muldivdf3 and _arm_muldivsf3 +# inclusion create when only multiplication is used, thus avoiding pulling in +# useless division code. +ifneq (__ARM_ARCH_ISA_THUMB 1,$(ARM_ISA)$(THUMB1_ISA)) +LIB1ASMFUNCS += _arm_muldf3 _arm_mulsf3 +endif +endif # !__symbian__ + # For most CPUs we have an assembly soft-float implementations. # However this is not true for ARMv6M. Here we want to use the soft-fp C # implementation. The soft-fp code is only build for ARMv6M. This pulls -- 2.19.1