diff --git a/Makeconfig b/Makeconfig
index 901e253..8a7b5f2 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -1124,7 +1124,7 @@ endif
 # emitted into sysd-rules.  A sysdeps Makeconfig fragment can
 # add its own special object file prefix to this list with e.g. foo-%:%
 # to have foo-*.? compiled from *.? using $(foo-CPPFLAGS).
-sysd-rules-patterns := %:% rtld-%:rtld-% rtld-%:% m_%:s_%
+sysd-rules-patterns := %:% rtld-%:rtld-% rtld-%:%
 
 # Let sysdeps/ subdirs contain a Makeconfig fragment for us to include here.
 sysdep-makeconfigs := $(wildcard $(+sysdep_dirs:=/Makeconfig))
diff --git a/math/Makefile b/math/Makefile
index 89002a8..14f8f42 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -43,6 +43,18 @@ libm-support = s_lib_version s_matherr s_signgam			\
 	       fesetenv feupdateenv t_exp fedisblxcpt feenablxcpt	\
 	       fegetexcept
 
+# These functions are generated from a common source with a select macros
+# for each type they built for.  There is an explicit underscore between
+# the function name and the type suffix to simplify matching to the
+# rule used to build it.  These all build from a common b_func.c file.
+#
+# Similarly, a platform can override any of these generated functions
+# (after type suffix substitution occurs) by adding a fragment which
+# defines libm-gen-calls-override and lists each function which should
+# not use the default version. If declared, it is assumed the target
+# will match the name s_<func><type suffix>
+gen-libm-calls = g_carg_F g_conj_F g_cimag_F g_creal_F g_cabs_F
+
 libm-calls =								  \
 	e_acosF e_acoshF e_asinF e_atan2F e_atanhF e_coshF e_expF e_fmodF \
 	e_hypotF e_j0F e_j1F e_jnF e_lgammaF_r e_logF e_log10F e_powF	  \
@@ -59,13 +71,13 @@ libm-calls =								  \
 	w_ilogbF							  \
 	s_fpclassifyF s_fmaxF s_fminF s_fdimF s_nanF s_truncF		  \
 	s_remquoF e_log2F e_exp2F s_roundF s_nearbyintF s_sincosF	  \
-	conjF cimagF crealF cabsF cargF s_cexpF s_csinhF s_ccoshF s_clogF \
+	s_cexpF s_csinhF s_ccoshF s_clogF				  \
 	s_catanF s_casinF s_ccosF s_csinF s_ctanF s_ctanhF s_cacosF	  \
 	s_casinhF s_cacoshF s_catanhF s_csqrtF s_cpowF s_cprojF s_clog10F \
 	s_fmaF s_lrintF s_llrintF s_lroundF s_llroundF e_exp10F w_log2F	  \
 	s_issignalingF $(calls:s_%=m_%) x2y2m1F k_casinhF		  \
 	gamma_productF lgamma_negF lgamma_productF			  \
-	s_nextupF s_nextdownF
+	s_nextupF s_nextdownF $(gen-libm-calls)
 
 libm-compat-calls-ldouble-yes = w_lgamma_compatl k_standardl
 libm-compat-calls = w_lgamma_compatf w_lgamma_compat k_standard k_standardf \
@@ -105,7 +117,9 @@ type-float-routines :=
 type-foreach = $(foreach t,$(types),$(subst F,$(type-$(t)-suffix),$(1)))
 
 libm-routines = $(strip $(libm-support) $(libm-compat-calls)		\
-			$(call type-foreach, $(libm-calls))		\
+			$(filter-out $(libm-gen-calls-override),	\
+				$(call type-foreach, $(libm-calls)))	\
+			$(libm-gen-replacement-calls)			\
 			$(foreach t, $(types), $(type-$(t)-routines))) 	\
 
 # These functions are in libc instead of libm because __printf_fp
@@ -118,6 +132,9 @@ calls = s_isinfF s_isnanF s_finiteF s_copysignF s_modfF s_scalbnF s_frexpF \
 generated += $(foreach s,.c .S,$(call type-foreach, $(calls:s_%=m_%$(s))))
 routines = $(call type-foreach, $(calls))
 
+# Wrappers and what not are generated per type to keep the noise down.
+generated += $(foreach s,.c .S,$(call type-foreach,$(gen-libm-calls:%=%$(s))))
+
 ifeq ($(build-mathvec),yes)
 # We need to install libm.so as linker script
 # for more comfortable use of vector math library.
@@ -303,6 +320,34 @@ endef
 object-suffixes-left := $(all-object-suffixes)
 include $(o-iterator)
 
+# Generated per-type files.
+#
+# Suffixes for each generated file.  This hackery makes it possible
+# to correctly identify name of the templated file.
+gen-suffixes := $(foreach s,$(all-object-suffixes), \
+                       $(foreach t,$(types),_$(type-$(t)-suffix)$s))
+
+# Add special flags to control how the templated functions
+# are built.
+g_CPPFLAGS = -include math-type-macros.h
+g__fCPPFLAGS = $(g_CPPFLAGS) -DM_TYPE=M_FLOAT
+g__CPPFLAGS = $(g_CPPFLAGS) -DM_TYPE=M_DOUBLE
+g__lCPPFLAGS = $(g_CPPFLAGS) -DM_TYPE=M_LDOUBLE
+
+# Like m_% above, this builds the generic sources.  Makeconfig
+# enumerates the sysd-rules for overriding.
+define o-iterator-doit
+$(objpfx)g_%$o: b_%.c $(before-compile); $$(compile-command.c)
+endef
+object-suffixes-left := $(gen-suffixes)
+include $(o-iterator)
+
+# Tack on the appropriate CPPFLAGS to match sysd-rules
+define o-iterator-doit
+$(objpfx)g_%$o: CPPFLAGS += $(g_$(basename $o)CPPFLAGS)
+endef
+object-suffixes-left := $(gen-suffixes)
+include $(o-iterator)
 
 # This file defines the default _LIB_VERSION variable that controls
 # the error return conventions for the math functions.
diff --git a/math/b_cabs.c b/math/b_cabs.c
new file mode 100644
index 0000000..64265f1
--- /dev/null
+++ b/math/b_cabs.c
@@ -0,0 +1,33 @@
+/* Return the complex absolute value of complex float type.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <math.h>
+
+FLOAT
+M_SUF (__cabs) (CFLOAT z)
+{
+  return M_SUF (__hypot) (__real__ z, __imag__ z);
+}
+
+declare_mgen_alias (__cabs, cabs)
+
+#if M_LIBM_NEED_COMPAT (cabs)
+  declare_mgen_libm_compat (__cabs, cabs)
+#endif
diff --git a/math/b_carg.c b/math/b_carg.c
new file mode 100644
index 0000000..004e14d
--- /dev/null
+++ b/math/b_carg.c
@@ -0,0 +1,33 @@
+/* Compute argument of complex float type.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <math.h>
+
+FLOAT
+M_SUF (__carg) (CFLOAT x)
+{
+  return M_SUF (__atan2) (__imag__ x, __real__ x);
+}
+
+declare_mgen_alias (__carg, carg)
+
+#if M_LIBM_NEED_COMPAT (carg)
+  declare_mgen_libm_compat (__carg, carg)
+#endif
diff --git a/math/b_cimag.c b/math/b_cimag.c
new file mode 100644
index 0000000..73450f3
--- /dev/null
+++ b/math/b_cimag.c
@@ -0,0 +1,32 @@
+/* Return imaginary part of complex float type.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+
+FLOAT
+M_SUF (__cimag) (CFLOAT z)
+{
+  return __imag__ z;
+}
+
+declare_mgen_alias (__cimag, cimag)
+
+#if M_LIBM_NEED_COMPAT (cimag)
+  declare_mgen_libm_compat (__cimag, cimag)
+#endif
diff --git a/math/b_conj.c b/math/b_conj.c
new file mode 100644
index 0000000..979a759
--- /dev/null
+++ b/math/b_conj.c
@@ -0,0 +1,32 @@
+/* Return complex conjugate of complex float type.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+
+CFLOAT
+M_SUF (__conj) (CFLOAT z)
+{
+  return ~z;
+}
+
+declare_mgen_alias (__conj, conj)
+
+#if M_LIBM_NEED_COMPAT (conj)
+  declare_mgen_libm_compat (__conj, conj)
+#endif
diff --git a/math/b_creal.c b/math/b_creal.c
new file mode 100644
index 0000000..b92e0a3
--- /dev/null
+++ b/math/b_creal.c
@@ -0,0 +1,32 @@
+/* Return real part of complex float type.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+
+FLOAT
+M_SUF (__creal) (CFLOAT z)
+{
+  return __real__ z;
+}
+
+declare_mgen_alias (__creal, creal)
+
+#if M_LIBM_NEED_COMPAT (creal)
+  declare_mgen_libm_compat (__creal, creal)
+#endif
diff --git a/math/cabs.c b/math/cabs.c
deleted file mode 100644
index d7e0665..0000000
--- a/math/cabs.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Return the complex absolute value of double complex value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-#include <math.h>
-
-double
-__cabs (double _Complex z)
-{
-  return __hypot (__real__ z, __imag__ z);
-}
-weak_alias (__cabs, cabs)
-#ifdef NO_LONG_DOUBLE
-strong_alias (__cabs, __cabsl)
-weak_alias (__cabs, cabsl)
-#endif
diff --git a/math/cabsf.c b/math/cabsf.c
deleted file mode 100644
index 431a244..0000000
--- a/math/cabsf.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Return the complex absolute value of float complex value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-#include <math.h>
-
-float
-__cabsf (float _Complex z)
-{
-  return __hypotf (__real__ z, __imag__ z);
-}
-weak_alias (__cabsf, cabsf)
diff --git a/math/cabsl.c b/math/cabsl.c
deleted file mode 100644
index d87e3a2..0000000
--- a/math/cabsl.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Return the complex absolute value of long double complex value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-#include <math.h>
-
-long double
-__cabsl (long double _Complex z)
-{
-  return __hypotl (__real__ z, __imag__ z);
-}
-weak_alias (__cabsl, cabsl)
diff --git a/math/carg.c b/math/carg.c
deleted file mode 100644
index 61f1e0d..0000000
--- a/math/carg.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Compute argument of complex double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-#include <math.h>
-
-double
-__carg (__complex__ double x)
-{
-  return __atan2 (__imag__ x, __real__ x);
-}
-weak_alias (__carg, carg)
-#ifdef NO_LONG_DOUBLE
-strong_alias (__carg, __cargl)
-weak_alias (__carg, cargl)
-#endif
diff --git a/math/cargf.c b/math/cargf.c
deleted file mode 100644
index 620db3e..0000000
--- a/math/cargf.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Compute argument of complex float value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-#include <math.h>
-
-float
-__cargf (__complex__ float x)
-{
-  return __atan2f (__imag__ x, __real__ x);
-}
-weak_alias (__cargf, cargf)
diff --git a/math/cargl.c b/math/cargl.c
deleted file mode 100644
index 31b7292..0000000
--- a/math/cargl.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Compute argument of complex long double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-#include <math.h>
-
-long double
-__cargl (__complex__ long double x)
-{
-  return __atan2l (__imag__ x, __real__ x);
-}
-weak_alias (__cargl, cargl)
diff --git a/math/cimag.c b/math/cimag.c
deleted file mode 100644
index 1807ac2..0000000
--- a/math/cimag.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Return imaginary part of complex double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-double
-__cimag (double _Complex z)
-{
-  return __imag__ z;
-}
-weak_alias (__cimag, cimag)
-#ifdef NO_LONG_DOUBLE
-strong_alias (__cimag, __cimagl)
-weak_alias (__cimag, cimagl)
-#endif
diff --git a/math/cimagf.c b/math/cimagf.c
deleted file mode 100644
index 67c37f4..0000000
--- a/math/cimagf.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Return imaginary part of complex float value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-float
-__cimagf (float _Complex z)
-{
-  return __imag__ z;
-}
-weak_alias (__cimagf, cimagf)
diff --git a/math/cimagl.c b/math/cimagl.c
deleted file mode 100644
index c1d0910..0000000
--- a/math/cimagl.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Return imaginary part of complex long double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-long double
-__cimagl (long double _Complex z)
-{
-  return __imag__ z;
-}
-weak_alias (__cimagl, cimagl)
diff --git a/math/conj.c b/math/conj.c
deleted file mode 100644
index d282985..0000000
--- a/math/conj.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Return complex conjugate of complex double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-double _Complex
-__conj (double _Complex z)
-{
-  return ~z;
-}
-weak_alias (__conj, conj)
-#ifdef NO_LONG_DOUBLE
-strong_alias (__conj, __conjl)
-weak_alias (__conj, conjl)
-#endif
diff --git a/math/conjf.c b/math/conjf.c
deleted file mode 100644
index 3587c94..0000000
--- a/math/conjf.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Return complex conjugate of complex float value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-float _Complex
-__conjf (float _Complex z)
-{
-  return ~z;
-}
-weak_alias (__conjf, conjf)
diff --git a/math/conjl.c b/math/conjl.c
deleted file mode 100644
index 55bb393..0000000
--- a/math/conjl.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Return complex conjugate of complex long double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-long double _Complex
-__conjl (long double _Complex z)
-{
-  return ~z;
-}
-weak_alias (__conjl, conjl)
diff --git a/math/creal.c b/math/creal.c
deleted file mode 100644
index 231d3b0..0000000
--- a/math/creal.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Return real part of complex double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-double
-__creal (double _Complex z)
-{
-  return __real__ z;
-}
-weak_alias (__creal, creal)
-#ifdef NO_LONG_DOUBLE
-strong_alias (__creal, __creall)
-weak_alias (__creal, creall)
-#endif
diff --git a/math/crealf.c b/math/crealf.c
deleted file mode 100644
index 5883849..0000000
--- a/math/crealf.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Return real part of complex float value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-float
-__crealf (float _Complex z)
-{
-  return __real__ z;
-}
-weak_alias (__crealf, crealf)
diff --git a/math/creall.c b/math/creall.c
deleted file mode 100644
index 4a31557..0000000
--- a/math/creall.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Return real part of complex long double value.
-   Copyright (C) 1997-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <complex.h>
-
-long double
-__creall (long double _Complex z)
-{
-  return __real__ z;
-}
-weak_alias (__creall, creall)
diff --git a/scripts/sysd-rules.awk b/scripts/sysd-rules.awk
index 69af400..ccf1dff 100644
--- a/scripts/sysd-rules.awk
+++ b/scripts/sysd-rules.awk
@@ -18,6 +18,9 @@ BEGIN {
   # They are no in particular order.  We need to sort them so that
   # the longest TARGET is first, and, among elements with the same
   # TARGET, the longest DEP is first.
+  #
+  # If two TARGETs have the same length DEP, the first TARGET is
+  # always listed first.
   for (i = 1; i <= npatterns; ++i) {
     if (split(patterns[i], td, ":") != 2) {
       msg = "bad sysd-rules-patterns element '" patterns[i] "'";
@@ -25,7 +28,7 @@ BEGIN {
       exit 2;
     }
     target_order = sprintf("%09d", npatterns + 1 - length(td[1]));
-    dep_order = sprintf("%09d", npatterns - length(td[2]));
+    dep_order = sprintf("%09d%03d", npatterns - length(td[2]), i);
     sort_patterns[target_order SUBSEP dep_order] = patterns[i];
   }
   asorti(sort_patterns, map_patterns);
diff --git a/sysdeps/alpha/fpu/Makefile b/sysdeps/alpha/fpu/Makefile
new file mode 100644
index 0000000..c49c302
--- /dev/null
+++ b/sysdeps/alpha/fpu/Makefile
@@ -0,0 +1,4 @@
+# Inhibit generation of these math files as they are supplied via
+# the respectic s_*.c versions here.
+libm-gen-calls-override = g_cabs_f g_carg_f g_cimag_f g_creal_f g_conj_f
+libm-gen-replacement-calls = cabsf cargf cimagf crealf conjf
diff --git a/sysdeps/generic/math-type-macros.h b/sysdeps/generic/math-type-macros.h
new file mode 100644
index 0000000..3befde1
--- /dev/null
+++ b/sysdeps/generic/math-type-macros.h
@@ -0,0 +1,159 @@
+/* Helper macros for type generic function implementations within libm.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MATH_TYPE_MACROS
+#define _MATH_TYPE_MACROS
+
+#define M_FLOAT 1
+#define M_DOUBLE 2
+#define M_LDOUBLE 3
+
+#if M_TYPE == M_FLOAT
+# define M_PFX FLT
+# define M_LIT(c) c ## f
+/* Use the double version instead.  */
+# define M_MLIT(c) c
+# define M_SUF(c) c ## f
+# define M_FUNC(c) c ## f
+# define FLOAT float
+# define CFLOAT __complex__ float
+# define M_HUGE_VAL HUGE_VALF
+#elif M_TYPE == M_DOUBLE
+# define M_PFX DBL
+# define M_LIT(c) c
+# define M_MLIT(c) c
+# define M_SUF(c) c
+# define M_FUNC(c) c
+# define FLOAT double
+# define CFLOAT __complex__ double
+# define M_HUGE_VAL HUGE_VAL
+#elif M_TYPE == M_LDOUBLE
+# define M_PFX LDBL
+# define M_LIT(c) c ## L
+# define M_MLIT(c) c ## l
+# define M_SUF(c) c ## l
+# define M_FUNC(c) c ## l
+# define FLOAT long double
+# define CFLOAT __complex__ long double
+# define M_HUGE_VAL HUGE_VALL
+#else
+# error Error: M_TYPE is not a known floating point type
+#endif
+
+#define __M_CONCAT(a,b) a ## b
+#define __M_CONCATX(a,b) __M_CONCAT(a,b)
+
+#define M_NAN M_FUNC (__nan) ("")
+#define M_MAX_EXP __M_CONCATX (M_PFX, _MAX_EXP)
+#define M_MIN __M_CONCATX (M_PFX, _MIN)
+#define M_MAX __M_CONCATX (M_PFX, _MAX)
+#define M_MANT_DIG __M_CONCATX (M_PFX, _MANT_DIG)
+
+/* Helper macros for commonly used functions.  */
+#define M_COPYSIGN M_FUNC (__copysign)
+#define M_FABS M_FUNC (fabs)
+#define M_SINCOS M_FUNC (__sincos)
+#define M_SCALBN M_FUNC (__scalbn)
+#define M_LOG1P M_FUNC (__log1p)
+
+#define M_ATAN2 M_FUNC (__ieee754_atan2)
+#define M_COSH M_FUNC (__ieee754_cosh)
+#define M_EXP M_FUNC (__ieee754_exp)
+#define M_HYPOT M_FUNC (__ieee754_hypot)
+#define M_LOG M_FUNC (__ieee754_log)
+#define M_SINH M_FUNC (__ieee754_sinh)
+#define M_SQRT M_FUNC (__ieee754_sqrt)
+
+/* Needed to evaluate M_MANT_DIG below.  */
+#include <float.h>
+
+/* Use a special epsilon value for IBM long double
+   to avoid spurious overflows.  */
+#if M_MANT_DIG != 106
+# define M_EPSILON __M_CONCATX (M_PFX, _EPSILON)
+#else
+# define M_EPSILON 0x1p-106L
+#endif
+
+/* Enable overloading of function name to assist
+   reuse.  */
+#ifndef M_DECL_FUNC
+# define M_DECL_FUNC(f) M_FUNC(f)
+#endif
+
+/* Rules for aliasing the currently generated math files.  */
+
+/* Aliasing rules for float are straight forward.  */
+#if M_TYPE == M_FLOAT
+# define declare_mgen_alias(from, to) weak_alias (M_SUF (from), M_SUF (to))
+#endif
+
+/* Aliasing rules for double are sightly more
+   complicated.
+   1. long double == double.
+   2. long double used to be double.
+   3. double has always been unique. */
+#if M_TYPE == M_DOUBLE
+# if defined NO_LONG_DOUBLE
+#  define declare_mgen_alias(from, to)	    \
+    weak_alias (from, to)		    \
+    strong_alias (from, from ## l)	    \
+    weak_alias (from, to ## l)
+# else
+#  define declare_mgen_alias(from, to)	    \
+    weak_alias (M_SUF (from), M_SUF (to))
+# endif
+#endif
+
+/* Slightly simpler for long double.
+   1. long double used to be double.
+   2. long double has always been unique.  */
+#if M_TYPE == M_LDOUBLE
+# if defined LONG_DOUBLE_COMPAT_VERSION
+#  define declare_mgen_alias(from, to)		  \
+    long_double_symbol (libm, from ## l, to ## l);
+# else
+#  define declare_mgen_alias(from, to)	    \
+    weak_alias (M_SUF (from), M_SUF (to))
+# endif
+#endif
+
+#if ! defined declare_mgen_alias
+# error Alias rules not defined for M_TYPE
+#endif
+
+/* From case 2 for double, we may need to declare compat
+   aliases for double symbols mapping to long double.
+
+   This suffices for the majority of the complex functions.
+   More interesting cases need to be handled on a case by
+   case basis.  */
+#if M_TYPE == M_DOUBLE && defined LONG_DOUBLE_COMPAT_VERSION
+# define M_LIBM_NEED_COMPAT(f)				      \
+  LONG_DOUBLE_COMPAT (libm, LDOUBLE_ ## f ## l_libm_version)
+# define declare_mgen_libm_compat(from, to)	      \
+    compat_symbol (libm,			      \
+		   from,			      \
+		   to ## l,			      \
+		   LDOUBLE_ ## to ## l_libm_version);
+#else
+# define M_LIBM_NEED_COMPAT(func) 0
+# define declare_mgen_libm_compat(from, to)
+#endif
+
+#endif /* _MATH_TYPE_MACROS */
diff --git a/sysdeps/ieee754/Makeconfig b/sysdeps/ieee754/Makeconfig
new file mode 100644
index 0000000..15fd238
--- /dev/null
+++ b/sysdeps/ieee754/Makeconfig
@@ -0,0 +1,6 @@
+# Add the rules for generated math files in sysdeps
+# Not the perfect place, but close enough.
+#
+# Each type supported by libm should have a g_%_SUFFIX
+# pattern to match its suffix.
+sysd-rules-patterns += m_%:s_% g_%_f:b_% g_%_l:b_% g_%_:b_%
diff --git a/sysdeps/ieee754/ldbl-opt/cabs.c b/sysdeps/ieee754/ldbl-opt/cabs.c
deleted file mode 100644
index a181de2..0000000
--- a/sysdeps/ieee754/ldbl-opt/cabs.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#include <math/cabs.c>
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
-compat_symbol (libm, __cabs, cabsl, GLIBC_2_1);
-#endif
diff --git a/sysdeps/ieee754/ldbl-opt/cabsl.c b/sysdeps/ieee754/ldbl-opt/cabsl.c
deleted file mode 100644
index b861633..0000000
--- a/sysdeps/ieee754/ldbl-opt/cabsl.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#undef weak_alias
-#define weak_alias(n,a)
-#include <math/cabsl.c>
-long_double_symbol (libm, __cabsl, cabsl);
diff --git a/sysdeps/ieee754/ldbl-opt/carg.c b/sysdeps/ieee754/ldbl-opt/carg.c
deleted file mode 100644
index 2ed3581..0000000
--- a/sysdeps/ieee754/ldbl-opt/carg.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#include <math/carg.c>
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
-compat_symbol (libm, __carg, cargl, GLIBC_2_1);
-#endif
diff --git a/sysdeps/ieee754/ldbl-opt/cargl.c b/sysdeps/ieee754/ldbl-opt/cargl.c
deleted file mode 100644
index 952dc60..0000000
--- a/sysdeps/ieee754/ldbl-opt/cargl.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#undef weak_alias
-#define weak_alias(n,a)
-#include <math/cargl.c>
-long_double_symbol (libm, __cargl, cargl);
diff --git a/sysdeps/ieee754/ldbl-opt/cimag.c b/sysdeps/ieee754/ldbl-opt/cimag.c
deleted file mode 100644
index f805258..0000000
--- a/sysdeps/ieee754/ldbl-opt/cimag.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#include <math/cimag.c>
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
-compat_symbol (libm, __cimag, cimagl, GLIBC_2_1);
-#endif
diff --git a/sysdeps/ieee754/ldbl-opt/cimagl.c b/sysdeps/ieee754/ldbl-opt/cimagl.c
deleted file mode 100644
index 112365e..0000000
--- a/sysdeps/ieee754/ldbl-opt/cimagl.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#undef weak_alias
-#define weak_alias(n,a)
-#include <math/cimagl.c>
-long_double_symbol (libm, __cimagl, cimagl);
diff --git a/sysdeps/ieee754/ldbl-opt/conj.c b/sysdeps/ieee754/ldbl-opt/conj.c
deleted file mode 100644
index e4edade..0000000
--- a/sysdeps/ieee754/ldbl-opt/conj.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#include <math/conj.c>
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
-compat_symbol (libm, __conj, conjl, GLIBC_2_1);
-#endif
diff --git a/sysdeps/ieee754/ldbl-opt/conjl.c b/sysdeps/ieee754/ldbl-opt/conjl.c
deleted file mode 100644
index c98e0ed..0000000
--- a/sysdeps/ieee754/ldbl-opt/conjl.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#undef weak_alias
-#define weak_alias(n,a)
-#include <math/conjl.c>
-long_double_symbol (libm, __conjl, conjl);
diff --git a/sysdeps/ieee754/ldbl-opt/creal.c b/sysdeps/ieee754/ldbl-opt/creal.c
deleted file mode 100644
index 0d1c93e..0000000
--- a/sysdeps/ieee754/ldbl-opt/creal.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#include <math/creal.c>
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
-compat_symbol (libm, __creal, creall, GLIBC_2_1);
-#endif
diff --git a/sysdeps/ieee754/ldbl-opt/creall.c b/sysdeps/ieee754/ldbl-opt/creall.c
deleted file mode 100644
index 68fedd4..0000000
--- a/sysdeps/ieee754/ldbl-opt/creall.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-#include <math_ldbl_opt.h>
-#undef weak_alias
-#define weak_alias(n,a)
-#include <math/creall.c>
-long_double_symbol (libm, __creall, creall);
diff --git a/sysdeps/ieee754/ldbl-opt/math-type-macros.h b/sysdeps/ieee754/ldbl-opt/math-type-macros.h
new file mode 100644
index 0000000..f963f77
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-opt/math-type-macros.h
@@ -0,0 +1,11 @@
+/* Include the long double compatability support for generated math files.  */
+#include <math_ldbl_opt.h>
+
+/* Declare compat versions for generated functions.  */
+#define LDOUBLE_cabsl_libm_version GLIBC_2_1
+#define LDOUBLE_cargl_libm_version GLIBC_2_1
+#define LDOUBLE_cimagl_libm_version GLIBC_2_1
+#define LDOUBLE_conjl_libm_version GLIBC_2_1
+#define LDOUBLE_creall_libm_version GLIBC_2_1
+
+#include_next <math-type-macros.h>
