AVR-Libc comes with hand-optimized float support functions written in assembler. These functions use the same naming conventions like libgcc. There are situations where this name clashed lead to performance regression because the functions from libgcc are linked. One example are the new fixed-point support that convert fixed-point to/from float and reference float/int conversion functions from within libgcc.
The float implementation in libm.a have been discussed several times with the only result that it is very unlikely that the code will ever be integrated into libgcc because the original authors are no more around. And is is much less work to add a new configure switch than to port and integrate the code, given there were no license issues. One point against such an extension was that such change to the compiler establishes a dependency between the compiler and AVR-Libc, but this decision has been made long ago by accepting code that actually should had been added to libgcc -- but was not for whatever reason. This patch removes that performance regressions by removing the doubly implemented functions from libgcc by means of a new configure option --with-avrlibc. Moreover, some specs are adjusted so that -lm is treated very much like -lgcc so that the user need not specify -lm by hand for core float support like int/float conversions. Without this patch, LTO compilations also lead to performance regression because lto adds -plugin-opt=-pass-through=-lgcc etc. prior to the -lm specified by the user. Other cases where code is improved are C++ programs, see PR28718 for a discussion. There are less fails in gcc.dg/fixed-point, presumably because the rounding is as expected by the test cases, i.e. there are no rounding errors as mentioned in the review for PR54222: http://gcc.gnu.org/ml/gcc-patches/2012-08/msg01586.html Ok to install? Johann PR target/54461 * configure.ac (noconfigdirs,target=avr-*-*): Add target-newlib, target-libgloss if configured --with-avrlibc. * configure: Regenerate. libgcc/ PR target/54461 * config.host (tmake_file,host=avr-*-*): Add avr/t-avrlibc if configured --with-avrlibc. * config/avr/t-avrlibc: New file. gcc/ PR target/54461 * config.gcc (tm_file,target=avr-*-*): Add avr/avrlibc.h if configured --with-avrlibc. (tm_defines,target=avr-*-*): Add WITH_AVRLIBC if configured --with-avrlibc. * config/avr/avrlibc.h: New file. * config/avr/avr-c.c: Build-in define __WITH_AVRLIBC__ if configured --with-avrlibc.
Index: configure =================================================================== --- configure (revision 190887) +++ configure (working copy) @@ -3500,6 +3500,13 @@ case "${target}" in arm-*-riscix*) noconfigdirs="$noconfigdirs ld target-libgloss" ;; + avr-*-rtems*) + ;; + avr-*-*) + if test x${with_avrlibc} = xyes; then + noconfigdirs="$noconfigdirs target-newlib target-libgloss" + fi + ;; c4x-*-* | tic4x-*-*) noconfigdirs="$noconfigdirs target-libgloss" ;; Index: configure.ac =================================================================== --- configure.ac (revision 190887) +++ configure.ac (working copy) @@ -891,6 +891,13 @@ case "${target}" in arm-*-riscix*) noconfigdirs="$noconfigdirs ld target-libgloss" ;; + avr-*-rtems*) + ;; + avr-*-*) + if test x${with_avrlibc} = xyes; then + noconfigdirs="$noconfigdirs target-newlib target-libgloss" + fi + ;; c4x-*-* | tic4x-*-*) noconfigdirs="$noconfigdirs target-libgloss" ;; Index: libgcc/config/avr/t-avrlibc =================================================================== --- libgcc/config/avr/t-avrlibc (revision 0) +++ libgcc/config/avr/t-avrlibc (revision 0) @@ -0,0 +1,66 @@ +# This file is used with --with-avrlibc=yes +# +# AVR-Libc comes with hand-optimized float routines. +# For historical reasons, these routines live in AVR-Libc +# and not in libgcc and use the same function names like libgcc. +# To get the best support, i.e. always use the routines from +# AVR-Libc, we remove these routines from libgcc. +# +# See also PR54461. +# +# +# Arithmetic: +# __addsf3 __subsf3 __divsf3 __mulsf3 __negsf2 +# +# Comparison: +# __cmpsf2 __unordsf2 +# __eqsf2 __lesf2 __ltsf2 __nesf2 __gesf2 __gtsf2 +# +# Conversion: +# __fixsfdi __fixunssfdi __floatdisf __floatundisf +# __fixsfsi __fixunssfsi __floatsisf __floatunsisf +# +# +# These functions are contained in modules: +# +# _addsub_sf.o: __addsf3 __subsf3 +# _mul_sf.o: __mulsf3 +# _div_sf.o: __divsf3 +# _negate_sf.o: __negsf2 +# +# _compare_sf.o: __cmpsf2 +# _unord_sf.o: __unordsf2 +# _eq_sf.o: __eqsf2 +# _ne_sf.o: __nesf2 +# _ge_sf.o: __gesf2 +# _gt_sf.o: __gtsf2 +# _le_sf.o: __lesf2 +# _lt_sf.o: __ltsf2 +# +# _fixsfdi.o: __fixsfdi +# _fixunssfdi.o: __fixunssfdi +# _fixunssfsi.o: __fixunssfsi +# _floatdisf.o: __floatdisf +# _floatundisf.o: __floatundisf +# _sf_to_si.o: __fixsfsi +# _si_to_sf.o: __floatsisf +# _usi_to_sf.o: __floatunsisf + + +# SFmode +LIB2FUNCS_EXCLUDE += \ + _addsub_sf \ + _negate_sf \ + _mul_sf _div_sf \ + \ + _compare_sf \ + _unord_sf \ + _eq_sf _ne_sf \ + _gt_sf _ge_sf \ + _lt_sf _le_sf \ + \ + _si_to_sf _sf_to_si \ + _usi_to_sf _sf_to_usi \ + _fixunssfsi _fixsfdi \ + _fixunssfdi \ + _floatdisf _floatundisf Index: libgcc/config.host =================================================================== --- libgcc/config.host (revision 190873) +++ libgcc/config.host (working copy) @@ -380,6 +380,9 @@ avr-*-rtems*) avr-*-*) # Make HImode functions for AVR tmake_file="${cpu_type}/t-avr t-fpbit" + if test x${with_avrlibc} = xyes; then + tmake_file="$tmake_file ${cpu_type}/t-avrlibc" + fi tm_file="$tm_file avr/avr-lib.h" ;; bfin*-elf*) Index: gcc/config/avr/avr-c.c =================================================================== --- gcc/config/avr/avr-c.c (revision 190873) +++ gcc/config/avr/avr-c.c (working copy) @@ -148,6 +148,10 @@ avr_cpu_cpp_builtins (struct cpp_reader cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x", avr_current_arch->sfr_offset); +#ifdef WITH_AVRLIBC + cpp_define (pfile, "__WITH_AVRLIBC__"); +#endif /* WITH_AVRLIBC */ + /* Define builtin macros so that the user can easily query if or if not non-generic address spaces (and which) are supported. This is only supported for C. For C++, a language extension is needed Index: gcc/config/avr/avrlibc.h =================================================================== --- gcc/config/avr/avrlibc.h (revision 0) +++ gcc/config/avr/avrlibc.h (revision 0) @@ -0,0 +1,31 @@ +/* Definitions of target machine for the GNU compiler collection + for Atmel AVR micro controller. + Copyright (C) 2012 + Free Software Foundation, Inc. + Contributed by Georg-Johann Lay (a...@gjlay.de) + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* AVR-Libc implements functions from libgcc.a in libm.a, see PR54461. */ + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC \ + "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lgcc -lm }}}}}" + +#undef LINK_GCC_C_SEQUENCE_SPEC +#define LINK_GCC_C_SEQUENCE_SPEC \ + "--start-group %G %L --end-group" Index: gcc/config.gcc =================================================================== --- gcc/config.gcc (revision 190873) +++ gcc/config.gcc (working copy) @@ -892,6 +892,10 @@ avr-*-rtems*) ;; avr-*-*) tm_file="elfos.h avr/elf.h avr/avr.h dbxelf.h avr/avr-stdint.h" + if test x${with_avrlibc} = xyes; then + tm_file="${tm_file} ${cpu_type}/avrlibc.h" + tm_defines="${tm_defines} WITH_AVRLIBC" + fi tmake_file="avr/t-avr avr/t-multilib" use_gcc_stdint=wrap extra_gcc_objs="driver-avr.o avr-devices.o"