public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
@ 2011-08-23 19:04 Michael Meissner
  2011-08-24  8:18 ` Mike Stump
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Michael Meissner @ 2011-08-23 19:04 UTC (permalink / raw)
  To: gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 6445 bytes --]

Over the years, it has been a problem for ports like the PowerPC that have
more builtins than the standard list.  Code that references the built_in_decls
and implicit_built_in_decls arrays are supposed to check DECL_BUILT_IN_CLASS
being BUILT_IN_NORMAL first, but every so often code doesn't do this check, and
it checks random pieces of memory, because the backend builtin function number
is greater than the number of machine independent builtins.

This patch is an infrastructure patch that lets backends decide to merge their
builtin enumerations at the end of the standard set of enumerations.  Only the
PowerPC port is modified with this patch.  If this goes in, the port
maintainers for the other ports with a lot of builtins (x86, spu, etc.) can
decide whether to move to this new infrastructure.

This patch growes the bit field that has the builtin function number by one
bit.  Strictly speaking for the PowerPC, we don't need it just yet, but it
gives us a margin of safety.  Right now, there are about 730 machine
independent builtins and 950 PowerPC builtins, which gives us a margin of 350
more builtins before the field is full, if I didn't grow the size of the
builtin function bitfield.

When I was documenting the tm-bu-funcs.def file built by the Makefile, I
noticed there was a FIXME comment asking why tm_p.h existed, so I added an
explanation.

Originally I wanted to allow the MD file to allow all of the builtins to be
initialized when the main builtins are setup.  This would have fit into the
infrastructure, by having MD versions of builtin-attrs.def and
builtin-types.def.  However, the problem is Fortran doesn't use the C, C++, and
LTO common builtin infrastructure, but it does want to initialize the target
builtins via the targetm.init_builtins hook.  So I decided not to include that
support in this patch.

These are meant to be committed as a single patch, but I have separated the
patches into a machine indendepent patch, and one that moves the PowerPC to use
this new infrastructure.

I anticipate there will be additional patches in the powerpc builtin area to
allow target attributes and pragmas to enable new builtins, but that will be in
a later patch.  I wanted in this patch to have a fairly minimimal set of
changes.

I have bootstrapped and done make checks on the PowerPC with no regressions.
In addition, I have bootstrapped the x86_64 to make sure it continues to work
for a port that wasn't modified.  Are these patches ok to commit?

[gcc]
2011-08-23  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* doc/configfiles.texi (tm_p.h): Document why tm_p.h is needed.
	(tm-bu-funcs.def): Document the include file that includes the
	machine dependent builtin functions.

	* tree.h (struct tree_function_decl): Grow function code field by
	1 bit to allow for machines with lots of builtins.

	* builtins.def (BUILT_IN_NONE): Reserve builtin index 0 so it is
	not a legitimate builtin.
	(DEF_BUILTIN_MD): New macro for defining machine dependent
	builtins.
	(toplevel): Include tm-bu-funcs.def.

	* configure.ac (tm_builtin_funcs): New autoconf variable to merge
	backend builtins into the main builtin handling.  Include
	rs6000-builtin.def on rs6000.
	* configure: Regenerate.
	* config.gcc (rs6000*, powerpc*): Ditto.

	* Makefile.in (BUILTINS_DEF): Add support for merging machine
	dependent builtins at the end of the standard builtins.
	(BUILTIN_FUNCS_MD): Ditto.
	(c-family/c-common.o): Ditto.
	(mostlyclean): Ditto.
	(tm-bu-funcs.def): New header built that includes machine
	dependent builtins.

	* config/rs6000/rs6000-protos.h (rs6000_builtin_types): Move here
	from rs6000.h.  Adjust for merging the rs6000 builtins after the
	standard builtins.
	(rs6000_builtin_decls): Ditto.

	* config/rs6000/rs6000-builtin.def (toplevel): Add support for
	being included in builtins.def to define all rs6000 builtins after
	the standard builtins.  Delete RS6000_BUILTIN_EQUATE.
	(RS6000_BUILTIN_FIRST): New macros to mark start and end of
	various classes of builtins.  Replace existing overload start and
	end markers.
	(ALTIVEC_BUILTIN_FIRST): Ditto.
	(ALTIVEC_BUILTIN_OVERLOADED_FIRST): Ditto.
	(ALTIVEC_BUILTIN_OVERLOADED_LAST): Ditto.
	(ALTIVEC_BUILTIN_LAST): Ditto.
	(SPE_BUILTIN_FIRST): Ditto.
	(SPE_BUILTIN_LAST): Ditto.
	(PAIRED_BUILTIN_FIRST): Ditto.
	(PAIRED_BUILTIN_LAST): Ditto.
	(VSX_BUILTIN_FIRST): Ditto.
	(VSX_BUILTIN_OVERLOADED_FIRST): Ditto.
	(VSX_BUILTIN_OVERLOADED_LAST): Ditto.
	(VSX_BUILTIN_LAST): Ditto.
	(RS6000_BUILTIN_LAST): Ditto.
	(VECTOR_BUILTIN_*): Move so the builtins are in the Altivec
	range.

	* config/rs6000/rs6000-c.c (struct altivec_builtin_types): Adjust
	for merging the rs6000 builtins after the standard builtins.
	(altivec_overloaded_builtins): Ditto.

	* config/rs6000/rs6000.c (rs6000_builtin_decls): Adjust for merging
	the rs6000 builtins after the standard builtins.
	(struct builtin_description): Ditto.
	(builtin_classify): Ditto.
	(builtin_function_type): Ditto.
	(rs6000_builtin_decl): Ditto.
	(enable_mask_for_builtins): Ditto.
	(rs6000_builtin_vectorized_function): Ditto.
	(struct builtin_description_predicates): Ditto.
	(def_builtin): If function is already defined, ignore rather than
	causing an error.
	(altivec_expand_builtin): Use OVERLOADED_BUILTIN_P.
	(altivec_init_builtin): Ditto.
	(rs6000_init_builtin_types): Split initializing types from the
	rest of the builtin support.  Add initial steps to making
	rs6000_init_builtins be called more than one.  Drop testing for
	VSX for building basic types, just like occurs for Altivec, SPE,
	etc.
	(rs6000_init_builtins): Ditto.
	(rs6000_common_init_builtins): Ditto.

	* config/rs6000/rs6000.h (enum rs6000_builtins): Delete, merge
	rs6000 builtins to the end of the standard builtins.
	(rs6000_builtin_types): Move to rs6000-protos.h.
	(rs6000_builtin_decls): Ditto.
	(ALTIVEC_BUILTIN_P): New macros mapping builtin function index to
	machine type.
	(ALTIVEC_BUILTIN_OVERLOADED_P): Ditto.
	(VSX_BUILTIN_P): Ditto.
	(VSX_BUILTIN_OVERLOADED_P): Ditto.
	(OVERLOADED_BUILTIN_P): Ditto.
	(SPEC_BUILTIN_P): Ditto.
	(PAIRED_BUILTIN_P): Ditto.
	(MISC_BUILTIN_P): Ditto.

[gcc/lto]
2011-08-19  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* Make-lang.in (lto/lto-lang.o): Adjust dependencies for merging
	backend builtins into main builtins.

 

-- 
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
meissner@linux.vnet.ibm.com	fax +1 (978) 399-6899

[-- Attachment #2: gcc-power7.patch272-mi --]
[-- Type: text/plain, Size: 7987 bytes --]

Index: gcc/doc/configfiles.texi
===================================================================
--- gcc/doc/configfiles.texi	(revision 177990)
+++ gcc/doc/configfiles.texi	(working copy)
@@ -60,5 +60,17 @@ machine.
 @item
 @file{tm_p.h}, which includes the header @file{@var{machine}-protos.h}
 that contains prototypes for functions in the target @file{.c} file.
-FIXME: why is such a separate header necessary?
+The @file{tm_p.h} is needed because the @file{@var{machine}-protos.h}
+will often times include declarations that include RTL and TREE
+datatypes.  These references must be bracketed with @code{#ifdef
+RTX_CODE} and @code{#ifdef TREE_CODE} respecitively.  These
+declarations can't go in the normal @file{@var{machine}.h} file
+because that file is included before @file{rtl.h} and/or @file{tree.h}
+are included.  The @file{tm_p.h} is included after @file{rtl.h} or
+@file{tree.h} are included.
+@item
+@file{tm-bu-funcs.def}, includes the machine dependent builtin
+functions that use the @code{DEF_BUILTIN_MD} macro to reserve the
+machine dependent builtins in the master builtin enum list after the
+standard enumerations.
 @end itemize
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 177990)
+++ gcc/tree.h	(working copy)
@@ -3503,7 +3503,7 @@ struct GTY(()) tree_function_decl {
      DECL_FUNCTION_CODE.  Otherwise unused.
      ???  The bitfield needs to be able to hold all target function
 	  codes as well.  */
-  ENUM_BITFIELD(built_in_function) function_code : 11;
+  ENUM_BITFIELD(built_in_function) function_code : 12;
   ENUM_BITFIELD(built_in_class) built_in_class : 2;
 
   unsigned static_ctor_flag : 1;
@@ -3526,7 +3526,7 @@ struct GTY(()) tree_function_decl {
   unsigned looping_const_or_pure_flag : 1;
   unsigned has_debug_args_flag : 1;
 
-  /* 2 bits left */
+  /* 1 bit left */
 };
 
 /* The source language of the translation-unit.  */
Index: gcc/configure
===================================================================
--- gcc/configure	(revision 177990)
+++ gcc/configure	(working copy)
@@ -608,6 +608,7 @@ PPLINC
 PPLLIBS
 GMPINC
 GMPLIBS
+tm_builtin_funcs
 target_cpu_default
 fortran_target_objs
 cxx_target_objs
@@ -17913,7 +17914,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17916 "configure"
+#line 17917 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18019,7 +18020,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 18022 "configure"
+#line 18023 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -26796,6 +26797,7 @@ fi
 
 
 
+
 # Echo link setup.
 if test x${build} = x${host} ; then
   if test x${host} = x${target} ; then
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(revision 177990)
+++ gcc/builtins.def	(working copy)
@@ -134,6 +134,13 @@ along with GCC; see the file COPYING3.  
   DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, 0, 0, false, false, \
 	       false, 0, false, false)
 
+/* Allocate the enum and the name for a machine dependent builtin, but do not
+   actually define it here at all.  */
+#undef DEF_BUILTIN_MD
+#define DEF_BUILTIN_MD(ENUM, NAME) \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_MD, 0, 0, false, false, \
+	       false, 0, false, false)
+
 /* Builtin used by the implementation of GNU OpenMP.  None of these are
    actually implemented in the compiler; they're all in libgomp.  */
 #undef DEF_GOMP_BUILTIN
@@ -173,6 +180,10 @@ along with GCC; see the file COPYING3.  
 #undef ATTR_MATHFN_FPROUNDING_STORE
 #define ATTR_MATHFN_FPROUNDING_STORE ATTR_NOTHROW_LEAF_LIST
 
+/* Avoid problems with fields that are zeroed by making sure index 0 is not a
+   legitimate builtin.  */
+DEF_BUILTIN_STUB       (BUILT_IN_NONE, (const char *)0)
+
 /* Category: math builtins.  */
 DEF_LIB_BUILTIN        (BUILT_IN_ACOS, "acos", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSF, "acosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -789,3 +800,6 @@ DEF_BUILTIN_STUB (BUILT_IN_EH_COPY_VALUE
 
 /* OpenMP builtins.  */
 #include "omp-builtins.def"
+
+/* Target machine builtins.  */
+#include "tm-bu-funcs.def"
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 177990)
+++ gcc/configure.ac	(working copy)
@@ -4923,6 +4923,7 @@ AC_SUBST(c_target_objs)
 AC_SUBST(cxx_target_objs)
 AC_SUBST(fortran_target_objs)
 AC_SUBST(target_cpu_default)
+AC_SUBST(tm_builtin_funcs)
 
 AC_SUBST_FILE(language_hooks)
 
Index: gcc/lto/Make-lang.in
===================================================================
--- gcc/lto/Make-lang.in	(revision 177990)
+++ gcc/lto/Make-lang.in	(working copy)
@@ -79,7 +79,8 @@ $(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIB
 lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
 	flags.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
 	$(TARGET_H) $(LTO_H) $(GIMPLE_H) gtype-lto.h gt-lto-lto-lang.h \
-	$(EXPR_H) $(LTO_STREAMER_H)
+	$(EXPR_H) $(LTO_STREAMER_H) builtin-attrs.def builtin-types.def \
+	$(BUILTINS_DEF)
 lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
 	toplev.h $(TREE_H) $(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(TM_H) \
 	$(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 177990)
+++ gcc/config.gcc	(working copy)
@@ -186,7 +186,10 @@
 #  configure_default_options
 #			Set to an initializer for configure_default_options
 #			in configargs.h, based on --with-cpu et cetera.
-
+#
+#  tm_builtin_funcs	Set to additional files in the target directory to
+#			provide target specific builtin functions.
+#
 # The following variables are used in each case-construct to build up the
 # outgoing variables:
 #
@@ -238,6 +241,7 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
+tm_builtin_funcs=
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 177990)
+++ gcc/Makefile.in	(working copy)
@@ -909,7 +909,9 @@ RTL_H = $(RTL_BASE_H) genrtl.h vecir.h
 RTL_ERROR_H = $(RTL_H) $(DIAGNOSTIC_CORE_H)
 READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
 PARAMS_H = params.h params.def
-BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def
+BUILTIN_FUNCS_MD = @tm_builtin_funcs@
+BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
+  tm-bu-funcs.def $(BUILTIN_FUNCS_MD)
 INTERNAL_FN_DEF = internal-fn.def
 INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
 TREE_H = tree.h all-tree.def tree.def c-family/c-common.def \
@@ -1979,6 +1981,19 @@ $(T)crtbeginT.o: crtstuff.c $(GCC_PASSES
 	$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
 	  -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \
 	  -o $(T)crtbeginT$(objext)
+
+# Build the builtin include files that includes the standard builtin file along
+# with any machine dependent versions of those files.  Note, this files is
+# expected to be included multiple times, so don't use mkconfig.sh which adds
+# header guards
+tm-bu-funcs.def: s-bu-funcs; @true
+s-bu-funcs: Makefile
+	for inc in $(BUILTIN_FUNCS_MD); do \
+	  echo "#include \"$$inc\""; \
+	done > tmp-bu-funcs.def
+	$(SHELL) $(srcdir)/../move-if-change tmp-bu-funcs.def tm-bu-funcs.def
+	$(STAMP) s-bu-funcs
+
 #\f
 # Compiling object files from source files.
 
@@ -4511,6 +4526,8 @@ mostlyclean: lang.mostlyclean
 	-rm -f gtype.state
 # Delete genchecksum outputs
 	-rm -f *-checksum.c
+# Delete builtin types, attributes, function include files
+	-rm -f tm-bu-funcs.def
 
 # Delete all files made by compilation
 # that don't exist in the distribution.

[-- Attachment #3: gcc-power7.patch272-ppc --]
[-- Type: text/plain, Size: 24913 bytes --]

Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 177990)
+++ gcc/config.gcc	(working copy)
@@ -403,6 +407,7 @@ powerpc*-*-*)
 	cpu_type=rs6000
 	extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
 	need_64bit_hwint=yes
+	tm_builtin_funcs="$(tm_builtin_funcs) config/rs6000/rs6000-builtin.def"
 	case x$with_cpu in
 	    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2|xe500mc64)
 		cpu_is_64bit=yes
@@ -412,6 +417,7 @@ powerpc*-*-*)
 	;;
 rs6000*-*-*)
 	need_64bit_hwint=yes
+	tm_builtin_funcs="$(tm_builtin_funcs) config/rs6000/rs6000-builtin.def"
 	extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
 	;;
 score*-*-*)
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 177990)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -195,4 +195,10 @@ void rs6000_final_prescan_insn (rtx, rtx
 extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
 extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES];
 extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER];
+
+#ifdef TREE_CODE
+extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
+extern GTY(()) tree rs6000_builtin_decls[END_BUILTINS];
+#endif
+
 #endif  /* rs6000-protos.h */
Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(revision 177990)
+++ gcc/config/rs6000/rs6000-builtin.def	(working copy)
@@ -24,9 +24,17 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* Before including this file, two macros must be defined:
-   RS6000_BUILTIN	 -- 2 arguments, the enum name, and classification
-   RS6000_BUILTIN_EQUATE -- 2 arguments, enum name and value */
+/* In rs6000.c, the macro RS6000_BUILTIN is defined which initializes the
+   builtin_classify array.  Outside of rs6000.c, this is included by
+   builtins.def, and we use DEF_BUILTIN_MD to reserved the enumeration.  */
+
+#ifndef RS6000_BUILTIN
+#define RS6000_BUILTIN(ENUM, CLASS) DEF_BUILTIN_MD (ENUM, (const char *)0)
+#define UNDEF_RS6000_BUILTIN
+#endif
+
+#undef RS6000_BUILTIN_FIRST
+#define RS6000_BUILTIN_FIRST	ALTIVEC_BUILTIN_ST_INTERNAL_4si
 
 /* AltiVec builtins.  */
 RS6000_BUILTIN(ALTIVEC_BUILTIN_ST_INTERNAL_4si,		RS6000_BTC_MEM)
@@ -276,13 +284,20 @@ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_EXT_V
 RS6000_BUILTIN(ALTIVEC_BUILTIN_COPYSIGN_V4SF,		RS6000_BTC_CONST)
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VRECIPFP,		RS6000_BTC_FP_PURE)
 
+/* Combined VSX/Altivec builtins.  */
+RS6000_BUILTIN(VECTOR_BUILTIN_FLOAT_V4SI_V4SF,		RS6000_BTC_FP_PURE)
+RS6000_BUILTIN(VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,	RS6000_BTC_FP_PURE)
+RS6000_BUILTIN(VECTOR_BUILTIN_FIX_V4SF_V4SI,		RS6000_BTC_FP_PURE)
+RS6000_BUILTIN(VECTOR_BUILTIN_FIXUNS_V4SF_V4SI,		RS6000_BTC_FP_PURE)
+
 /* Altivec overloaded builtins.  */
 /* For now, don't set the classification for overloaded functions.
    The function should be converted to the type specific instruction
    before we get to the point about classifying the builtin type.  */
+#undef ALTIVEC_BUILTIN_OVERLOADED_FIRST
+#define ALTIVEC_BUILTIN_OVERLOADED_FIRST ALTIVEC_BUILTIN_VCMPEQ_P
+
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPEQ_P,		RS6000_BTC_MISC)
-RS6000_BUILTIN_EQUATE(ALTIVEC_BUILTIN_OVERLOADED_FIRST,
-		      ALTIVEC_BUILTIN_VCMPEQ_P)
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPGT_P,		RS6000_BTC_MISC)
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPGE_P,		RS6000_BTC_MISC)
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_ABS,			RS6000_BTC_MISC)
@@ -512,10 +527,17 @@ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STEP,
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_PROMOTE,		RS6000_BTC_MISC)
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_INSERT,		RS6000_BTC_MISC)
 RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_SPLATS,		RS6000_BTC_MISC)
-RS6000_BUILTIN_EQUATE(ALTIVEC_BUILTIN_OVERLOADED_LAST,
-		      ALTIVEC_BUILTIN_VEC_SPLATS)
+
+#undef ALTIVEC_BUILTIN_OVERLOADED_LAST
+#define ALTIVEC_BUILTIN_OVERLOADED_LAST	ALTIVEC_BUILTIN_VEC_SPLATS
+
+#undef ALTIVEC_BUILTIN_LAST
+#define ALTIVEC_BUILTIN_LAST		ALTIVEC_BUILTIN_VEC_SPLATS
 
 /* SPE builtins.  */
+#undef SPE_BUILTIN_FIRST
+#define SPE_BUILTIN_FIRST		SPE_BUILTIN_EVADDW
+
 RS6000_BUILTIN(SPE_BUILTIN_EVADDW,			RS6000_BTC_MISC)
 RS6000_BUILTIN(SPE_BUILTIN_EVAND,			RS6000_BTC_MISC)
 RS6000_BUILTIN(SPE_BUILTIN_EVANDC,			RS6000_BTC_MISC)
@@ -750,7 +772,13 @@ RS6000_BUILTIN(SPE_BUILTIN_MTSPEFSCR,			
 RS6000_BUILTIN(SPE_BUILTIN_MFSPEFSCR,			RS6000_BTC_MISC)
 RS6000_BUILTIN(SPE_BUILTIN_BRINC,			RS6000_BTC_MISC)
 
+#undef SPE_BUILTIN_LAST
+#define SPE_BUILTIN_LAST	SPE_BUILTIN_BRINC
+
 /* PAIRED builtins.  */
+#undef PAIRED_BUILTIN_FIRST
+#define PAIRED_BUILTIN_FIRST	PAIRED_BUILTIN_DIVV2SF3
+
 RS6000_BUILTIN(PAIRED_BUILTIN_DIVV2SF3,			RS6000_BTC_MISC)
 RS6000_BUILTIN(PAIRED_BUILTIN_ABSV2SF2,			RS6000_BTC_MISC)
 RS6000_BUILTIN(PAIRED_BUILTIN_NEGV2SF2,			RS6000_BTC_MISC)
@@ -780,7 +808,13 @@ RS6000_BUILTIN(PAIRED_BUILTIN_SELV2SF4,	
 RS6000_BUILTIN(PAIRED_BUILTIN_CMPU0,			RS6000_BTC_MISC)
 RS6000_BUILTIN(PAIRED_BUILTIN_CMPU1,			RS6000_BTC_MISC)
 
+#undef PAIRED_BUILTIN_LAST
+#define PAIRED_BUILTIN_LAST	PAIRED_BUILTIN_CMPU1
+
   /* VSX builtins.  */
+#undef VSX_BUILTIN_FIRST
+#define VSX_BUILTIN_FIRST	VSX_BUILTIN_LXSDX
+
 RS6000_BUILTIN(VSX_BUILTIN_LXSDX,			RS6000_BTC_MEM)
 RS6000_BUILTIN(VSX_BUILTIN_LXVD2X_V2DF,			RS6000_BTC_MEM)
 RS6000_BUILTIN(VSX_BUILTIN_LXVD2X_V2DI,			RS6000_BTC_MEM)
@@ -982,9 +1016,10 @@ RS6000_BUILTIN(VSX_BUILTIN_RECIP_V2DF,		
 
 /* VSX overloaded builtins, add the overloaded functions not present in
    Altivec.  */
+#undef VSX_BUILTIN_OVERLOADED_FIRST
+#define VSX_BUILTIN_OVERLOADED_FIRST	VSX_BUILTIN_VEC_MUL
+
 RS6000_BUILTIN(VSX_BUILTIN_VEC_MUL,			RS6000_BTC_MISC)
-RS6000_BUILTIN_EQUATE(VSX_BUILTIN_OVERLOADED_FIRST,
-		      VSX_BUILTIN_VEC_MUL)
 RS6000_BUILTIN(VSX_BUILTIN_VEC_MSUB,			RS6000_BTC_MISC)
 RS6000_BUILTIN(VSX_BUILTIN_VEC_NMADD,			RS6000_BTC_MISC)
 RS6000_BUILTIN(VSX_BUITLIN_VEC_NMSUB,			RS6000_BTC_MISC)
@@ -997,16 +1032,17 @@ RS6000_BUILTIN(VSX_BUILTIN_VEC_XXSPLTD,	
 RS6000_BUILTIN(VSX_BUILTIN_VEC_XXSPLTW,			RS6000_BTC_MISC)
 RS6000_BUILTIN(VSX_BUILTIN_VEC_LD,			RS6000_BTC_MISC)
 RS6000_BUILTIN(VSX_BUILTIN_VEC_ST,			RS6000_BTC_MISC)
-RS6000_BUILTIN_EQUATE(VSX_BUILTIN_OVERLOADED_LAST,
-		      VSX_BUILTIN_VEC_ST)
 
-/* Combined VSX/Altivec builtins.  */
-RS6000_BUILTIN(VECTOR_BUILTIN_FLOAT_V4SI_V4SF,		RS6000_BTC_FP_PURE)
-RS6000_BUILTIN(VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,	RS6000_BTC_FP_PURE)
-RS6000_BUILTIN(VECTOR_BUILTIN_FIX_V4SF_V4SI,		RS6000_BTC_FP_PURE)
-RS6000_BUILTIN(VECTOR_BUILTIN_FIXUNS_V4SF_V4SI,		RS6000_BTC_FP_PURE)
+#undef VSX_BUILTIN_OVERLOADED_LAST
+#define VSX_BUILTIN_OVERLOADED_LAST	VSX_BUILTIN_VEC_ST
+
+#undef VSX_BUILTIN_LAST
+#define VSX_BUILTIN_LAST		VSX_BUILTIN_VEC_ST
 
 /* Power7 builtins, that aren't VSX instructions.  */
+#undef MISC_BUILTIN_FIRST
+#define MISC_BUILTIN_FIRST		POWER7_BUILTIN_BPERMD
+
 RS6000_BUILTIN(POWER7_BUILTIN_BPERMD,			RS6000_BTC_CONST)
 
 /* Miscellaneous builtins.  */
@@ -1018,3 +1054,16 @@ RS6000_BUILTIN(RS6000_BUILTIN_BSWAP_HI,	
 
 /* Darwin CfString builtin.  */
 RS6000_BUILTIN(RS6000_BUILTIN_CFSTRING,			RS6000_BTC_MISC)
+
+/* End marker.  */
+#undef MISC_BUILTIN_LAST
+#define MISC_BUILTIN_LAST	RS6000_BUILTIN_CFSTRING
+
+#undef RS6000_BUILTIN_LAST
+#define RS6000_BUILTIN_LAST	RS6000_BUILTIN_CFSTRING
+
+#ifdef UNDEF_RS6000_BUILTIN
+#undef UNDEF_RS6000_BUILTIN
+#undef RS6000_BUILTIN
+#endif
+
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 177990)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -446,8 +446,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
 \f
 struct altivec_builtin_types
 {
-  enum rs6000_builtins code;
-  enum rs6000_builtins overloaded_code;
+  enum built_in_function code;
+  enum built_in_function overloaded_code;
   signed char ret_type;
   signed char op1;
   signed char op2;
@@ -3334,7 +3334,7 @@ const struct altivec_builtin_types altiv
   { ALTIVEC_BUILTIN_VCMPGE_P, VSX_BUILTIN_XVCMPGEDP_P,
     RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
 
-  { (enum rs6000_builtins) 0, (enum rs6000_builtins) 0, 0, 0, 0, 0 }
+  { (enum built_in_function) 0, (enum built_in_function) 0, 0, 0, 0, 0 }
 };
 \f
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 177990)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -197,7 +197,7 @@ static int dbg_cost_ctrl;
 
 /* Built in types.  */
 tree rs6000_builtin_types[RS6000_BTI_MAX];
-tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
+tree rs6000_builtin_decls[END_BUILTINS];
 
 /* Flag to say the TOC is initialized */
 int toc_initialized;
@@ -221,7 +221,7 @@ struct builtin_description
   unsigned int mask;
   const enum insn_code icode;
   const char *const name;
-  const enum rs6000_builtins code;
+  const enum built_in_function code;
 };
 
 /* Describe the vector unit used for modes.  */
@@ -850,17 +850,20 @@ struct processor_costs ppca2_cost = {
 \f
 /* Table that classifies rs6000 builtin functions (pure, const, etc.).  */
 #undef RS6000_BUILTIN
-#undef RS6000_BUILTIN_EQUATE
 #define RS6000_BUILTIN(NAME, TYPE) TYPE,
-#define RS6000_BUILTIN_EQUATE(NAME, VALUE)
 
-static const enum rs6000_btc builtin_classify[(int)RS6000_BUILTIN_COUNT] =
+#define RS6000_BUILTIN_COUNT \
+  (((size_t)RS6000_BUILTIN_LAST) - (size_t)RS6000_BUILTIN_FIRST + 1)
+
+static const enum rs6000_btc builtin_classify[RS6000_BUILTIN_COUNT] =
 {
 #include "rs6000-builtin.def"
 };
 
 #undef RS6000_BUILTIN
-#undef RS6000_BUILTIN_EQUATE
+
+#define RS6000_BUILTIN_CLASSIFY(FN) \
+  builtin_classify [(size_t)(FN) - (size_t)RS6000_BUILTIN_FIRST]
 
 /* Support for -mveclibabi=<xxx> to control which vector library to use.  */
 static tree (*rs6000_veclib_handler) (tree, tree, tree);
@@ -1011,7 +1014,7 @@ static unsigned builtin_hash_function (c
 static int builtin_hash_eq (const void *, const void *);
 static tree builtin_function_type (enum machine_mode, enum machine_mode,
 				   enum machine_mode, enum machine_mode,
-				   enum rs6000_builtins, const char *name);
+				   enum built_in_function, const char *name);
 static void rs6000_common_init_builtins (void);
 static void rs6000_init_libfuncs (void);
 
@@ -1022,8 +1025,8 @@ static rtx paired_expand_stv_builtin (en
 static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx);
 
 static void enable_mask_for_builtins (struct builtin_description *, int,
-				      enum rs6000_builtins,
-				      enum rs6000_builtins);
+				      enum built_in_function,
+				      enum built_in_function);
 static void spe_init_builtins (void);
 static rtx spe_expand_builtin (tree, rtx, bool *);
 static rtx spe_expand_stv_builtin (enum insn_code, tree);
@@ -3962,8 +3965,8 @@ rs6000_builtin_vectorized_function (tree
 
   else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
     {
-      enum rs6000_builtins fn
-	= (enum rs6000_builtins)DECL_FUNCTION_CODE (fndecl);
+      enum built_in_function fn
+	= (enum built_in_function)DECL_FUNCTION_CODE (fndecl);
       switch (fn)
 	{
 	case RS6000_BUILTIN_RSQRTF:
@@ -9412,19 +9415,17 @@ rs6000_gimplify_va_arg (tree valist, tre
 static void
 def_builtin (int mask, const char *name, tree type, int code)
 {
-  if ((mask & target_flags) || TARGET_PAIRED_FLOAT)
+  if (!rs6000_builtin_decls[code]
+      && ((mask & target_flags) || TARGET_PAIRED_FLOAT))
     {
       tree t;
-      if (rs6000_builtin_decls[code])
-	fatal_error ("internal error: builtin function to %s already processed",
-		     name);
 
       rs6000_builtin_decls[code] = t =
         add_builtin_function (name, type, code, BUILT_IN_MD,
 			      NULL, NULL_TREE);
 
-      gcc_assert (code >= 0 && code < (int)RS6000_BUILTIN_COUNT);
-      switch (builtin_classify[code])
+      gcc_assert (IN_RANGE (code, RS6000_BUILTIN_FIRST, RS6000_BUILTIN_LAST));
+      switch (RS6000_BUILTIN_CLASSIFY (code))
 	{
 	default:
 	  gcc_unreachable ();
@@ -10064,7 +10065,7 @@ struct builtin_description_predicates
   const unsigned int mask;
   const enum insn_code icode;
   const char *const name;
-  const enum rs6000_builtins code;
+  const enum built_in_function code;
 };
 
 static const struct builtin_description_predicates bdesc_altivec_preds[] =
@@ -11165,10 +11166,7 @@ altivec_expand_builtin (tree exp, rtx ta
   enum machine_mode tmode, mode0;
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
 
-  if ((fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
-       && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
-      || (fcode >= VSX_BUILTIN_OVERLOADED_FIRST
-	  && fcode <= VSX_BUILTIN_OVERLOADED_LAST))
+  if (OVERLOADED_BUILTIN_P (fcode))
     {
       *expandedp = true;
       error ("unresolved overload for Altivec builtin %qF", fndecl);
@@ -11961,10 +11959,9 @@ rs6000_expand_builtin (tree exp, rtx tar
 }
 
 static void
-rs6000_init_builtins (void)
+rs6000_init_builtin_types (void)
 {
   tree tdecl;
-  tree ftype;
 
   V2SI_type_node = build_vector_type (intSI_type_node, 2);
   V2SF_type_node = build_vector_type (float_type_node, 2);
@@ -12121,42 +12118,56 @@ rs6000_init_builtins (void)
   TYPE_NAME (pixel_V8HI_type_node) = tdecl;
   (*lang_hooks.decls.pushdecl) (tdecl);
 
-  if (TARGET_VSX)
-    {
-      tdecl = build_decl (BUILTINS_LOCATION,
-			  TYPE_DECL, get_identifier ("__vector double"),
-			  V2DF_type_node);
-      TYPE_NAME (V2DF_type_node) = tdecl;
-      (*lang_hooks.decls.pushdecl) (tdecl);
-
-      tdecl = build_decl (BUILTINS_LOCATION,
-			  TYPE_DECL, get_identifier ("__vector long"),
-			  V2DI_type_node);
-      TYPE_NAME (V2DI_type_node) = tdecl;
-      (*lang_hooks.decls.pushdecl) (tdecl);
-
-      tdecl = build_decl (BUILTINS_LOCATION,
-			  TYPE_DECL, get_identifier ("__vector unsigned long"),
-			  unsigned_V2DI_type_node);
-      TYPE_NAME (unsigned_V2DI_type_node) = tdecl;
-      (*lang_hooks.decls.pushdecl) (tdecl);
-
-      tdecl = build_decl (BUILTINS_LOCATION,
-			  TYPE_DECL, get_identifier ("__vector __bool long"),
-			  bool_V2DI_type_node);
-      TYPE_NAME (bool_V2DI_type_node) = tdecl;
-      (*lang_hooks.decls.pushdecl) (tdecl);
-    }
+  tdecl = build_decl (BUILTINS_LOCATION,
+		      TYPE_DECL, get_identifier ("__vector double"),
+		      V2DF_type_node);
+  TYPE_NAME (V2DF_type_node) = tdecl;
+  (*lang_hooks.decls.pushdecl) (tdecl);
 
-  if (TARGET_PAIRED_FLOAT)
+  tdecl = build_decl (BUILTINS_LOCATION,
+		      TYPE_DECL, get_identifier ("__vector long"),
+		      V2DI_type_node);
+  TYPE_NAME (V2DI_type_node) = tdecl;
+  (*lang_hooks.decls.pushdecl) (tdecl);
+
+  tdecl = build_decl (BUILTINS_LOCATION,
+		      TYPE_DECL, get_identifier ("__vector unsigned long"),
+		      unsigned_V2DI_type_node);
+  TYPE_NAME (unsigned_V2DI_type_node) = tdecl;
+  (*lang_hooks.decls.pushdecl) (tdecl);
+
+  tdecl = build_decl (BUILTINS_LOCATION,
+		      TYPE_DECL, get_identifier ("__vector __bool long"),
+		      bool_V2DI_type_node);
+  TYPE_NAME (bool_V2DI_type_node) = tdecl;
+  (*lang_hooks.decls.pushdecl) (tdecl);
+}
+
+/* This function may be called multiple times if the user changes the machine
+   with the target attribute or pragma, so only create the builtins for a
+   particular class the first time where the target options were set.  */
+
+static void
+rs6000_init_builtins (void)
+{
+  static bool first_time = true;
+  tree ftype;
+
+  if (V2SI_type_node == NULL_TREE)
+    rs6000_init_builtin_types ();
+
+  if (TARGET_PAIRED_FLOAT && !rs6000_builtin_decls[PAIRED_BUILTIN_LX])
     paired_init_builtins ();
-  if (TARGET_SPE)
+
+  if (TARGET_SPE && !rs6000_builtin_decls[SPE_BUILTIN_MTSPEFSCR])
     spe_init_builtins ();
-  if (TARGET_ALTIVEC)
+
+  if (TARGET_ALTIVEC && !rs6000_builtin_decls[ALTIVEC_BUILTIN_MTVSCR])
     altivec_init_builtins ();
   if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT || TARGET_VSX)
     rs6000_common_init_builtins ();
-  if (TARGET_FRE)
+
+  if (TARGET_FRE && !rs6000_builtin_decls[RS6000_BUILTIN_RECIP])
     {
       ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
 				     RS6000_BUILTIN_RECIP,
@@ -12164,7 +12175,8 @@ rs6000_init_builtins (void)
       def_builtin (MASK_POPCNTB, "__builtin_recipdiv", ftype,
 		   RS6000_BUILTIN_RECIP);
     }
-  if (TARGET_FRES)
+
+  if (TARGET_FRES && !rs6000_builtin_decls[RS6000_BUILTIN_RECIPF])
     {
       ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode,
 				     RS6000_BUILTIN_RECIPF,
@@ -12172,7 +12184,8 @@ rs6000_init_builtins (void)
       def_builtin (MASK_PPC_GFXOPT, "__builtin_recipdivf", ftype,
 		   RS6000_BUILTIN_RECIPF);
     }
-  if (TARGET_FRSQRTE)
+
+  if (TARGET_FRSQRTE && !rs6000_builtin_decls[RS6000_BUILTIN_RSQRT])
     {
       ftype = builtin_function_type (DFmode, DFmode, VOIDmode, VOIDmode,
 				     RS6000_BUILTIN_RSQRT,
@@ -12180,7 +12193,8 @@ rs6000_init_builtins (void)
       def_builtin (MASK_PPC_GFXOPT, "__builtin_rsqrt", ftype,
 		   RS6000_BUILTIN_RSQRT);
     }
-  if (TARGET_FRSQRTES)
+
+  if (TARGET_FRSQRTES && !rs6000_builtin_decls[RS6000_BUILTIN_RSQRTF])
     {
       ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode,
 				     RS6000_BUILTIN_RSQRTF,
@@ -12188,7 +12202,8 @@ rs6000_init_builtins (void)
       def_builtin (MASK_PPC_GFXOPT, "__builtin_rsqrtf", ftype,
 		   RS6000_BUILTIN_RSQRTF);
     }
-  if (TARGET_POPCNTD)
+
+  if (TARGET_POPCNTD && !rs6000_builtin_decls[POWER7_BUILTIN_BPERMD])
     {
       enum machine_mode mode = (TARGET_64BIT) ? DImode : SImode;
       tree ftype = builtin_function_type (mode, mode, mode, VOIDmode,
@@ -12197,7 +12212,8 @@ rs6000_init_builtins (void)
       def_builtin (MASK_POPCNTD, "__builtin_bpermd", ftype,
 		   POWER7_BUILTIN_BPERMD);
     }
-  if (TARGET_POWERPC)
+
+  if (TARGET_POWERPC && !rs6000_builtin_decls[RS6000_BUILTIN_BSWAP_HI])
     {
       /* Don't use builtin_function_type here, as it maps HI/QI to SI.  */
       tree ftype = build_function_type_list (unsigned_intHI_type_node,
@@ -12207,15 +12223,20 @@ rs6000_init_builtins (void)
 		   RS6000_BUILTIN_BSWAP_HI);
     }
 
+  if (first_time)
+    {
+      first_time = false;
+
 #if TARGET_XCOFF
-  /* AIX libm provides clog as __clog.  */
-  if (built_in_decls [BUILT_IN_CLOG])
-    set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
+      /* AIX libm provides clog as __clog.  */
+      if (built_in_decls [BUILT_IN_CLOG])
+	set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
 #endif
 
 #ifdef SUBTARGET_INIT_BUILTINS
-  SUBTARGET_INIT_BUILTINS;
+      SUBTARGET_INIT_BUILTINS;
 #endif
+    }
 }
 
 /* Returns the rs6000 builtin decl for CODE.  */
@@ -12223,7 +12244,7 @@ rs6000_init_builtins (void)
 static tree
 rs6000_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
 {
-  if (code >= RS6000_BUILTIN_COUNT)
+  if (!IN_RANGE (code, RS6000_BUILTIN_FIRST, RS6000_BUILTIN_LAST))
     return error_mark_node;
 
   return rs6000_builtin_decls[code];
@@ -12236,8 +12257,8 @@ rs6000_builtin_decl (unsigned code, bool
    END is the builtin enum at which to end.  */
 static void
 enable_mask_for_builtins (struct builtin_description *desc, int size,
-			  enum rs6000_builtins start,
-			  enum rs6000_builtins end)
+			  enum built_in_function start,
+			  enum built_in_function end)
 {
   int i;
 
@@ -12762,12 +12783,8 @@ altivec_init_builtins (void)
     {
       enum machine_mode mode1;
       tree type;
-      bool is_overloaded = ((dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
-			     && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
-			    || (dp->code >= VSX_BUILTIN_OVERLOADED_FIRST
-				&& dp->code <= VSX_BUILTIN_OVERLOADED_LAST));
 
-      if (is_overloaded)
+      if (OVERLOADED_BUILTIN_P (dp->code))
 	mode1 = VOIDmode;
       else
 	mode1 = insn_data[dp->icode].operand[1].mode;
@@ -13014,7 +13031,7 @@ builtin_hash_eq (const void *h1, const v
 static tree
 builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
 		       enum machine_mode mode_arg1, enum machine_mode mode_arg2,
-		       enum rs6000_builtins builtin, const char *name)
+		       enum built_in_function builtin, const char *name)
 {
   struct builtin_hash_struct h;
   struct builtin_hash_struct *h2;
@@ -13184,13 +13201,11 @@ rs6000_common_init_builtins (void)
       int mask = d->mask;
 
       if ((mask != 0 && (mask & target_flags) == 0)
-	  || (mask == 0 && !TARGET_PAIRED_FLOAT))
+	  || (mask == 0 && !TARGET_PAIRED_FLOAT)
+	  || rs6000_builtin_decls[d->code] != NULL_TREE)
 	continue;
 
-      if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
-	   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
-	  || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
-	      && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
+      if (OVERLOADED_BUILTIN_P (d->code))
 	{
 	  if (! (type = opaque_ftype_opaque_opaque_opaque))
 	    type = opaque_ftype_opaque_opaque_opaque
@@ -13225,13 +13240,11 @@ rs6000_common_init_builtins (void)
       int mask = d->mask;
 
       if ((mask != 0 && (mask & target_flags) == 0)
-	  || (mask == 0 && !TARGET_PAIRED_FLOAT))
+	  || (mask == 0 && !TARGET_PAIRED_FLOAT)
+	  || rs6000_builtin_decls[d->code] != NULL_TREE)
 	continue;
 
-      if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
-	   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
-	  || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
-	      && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
+      if (OVERLOADED_BUILTIN_P (d->code))
 	{
 	  if (! (type = opaque_ftype_opaque_opaque))
 	    type = opaque_ftype_opaque_opaque
@@ -13288,13 +13301,11 @@ rs6000_common_init_builtins (void)
       int mask = d->mask;
 
       if ((mask != 0 && (mask & target_flags) == 0)
-	  || (mask == 0 && !TARGET_PAIRED_FLOAT))
+	  || (mask == 0 && !TARGET_PAIRED_FLOAT)
+	  || rs6000_builtin_decls[d->code] != NULL_TREE)
 	continue;
 
-      if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
-	   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
-	  || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
-	      && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
+      if (OVERLOADED_BUILTIN_P (d->code))
 	{
 	  if (! (type = opaque_ftype_opaque))
 	    type = opaque_ftype_opaque
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 177990)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -2258,6 +2258,7 @@ extern int frame_pointer_needed;
    flags.  */
 enum rs6000_btc
 {
+  RS6000_BTC_NONE,		/* not really a builtin, marker */
   RS6000_BTC_MISC,		/* assume builtin can do anything */
   RS6000_BTC_CONST,		/* builtin is a 'const' function.  */
   RS6000_BTC_PURE,		/* builtin is a 'pure' function.  */
@@ -2268,21 +2269,6 @@ enum rs6000_btc
 #define RS6000_BTC_MEM	RS6000_BTC_MISC	/* load/store touches memory */
 #define RS6000_BTC_SAT	RS6000_BTC_MISC	/* VMX saturate sets VSCR register */
 
-#undef RS6000_BUILTIN
-#undef RS6000_BUILTIN_EQUATE
-#define RS6000_BUILTIN(NAME, TYPE) NAME,
-#define RS6000_BUILTIN_EQUATE(NAME, VALUE) NAME = VALUE,
-
-enum rs6000_builtins
-{
-#include "rs6000-builtin.def"
-
-  RS6000_BUILTIN_COUNT
-};
-
-#undef RS6000_BUILTIN
-#undef RS6000_BUILTIN_EQUATE
-
 enum rs6000_builtin_type_index
 {
   RS6000_BTI_NOT_OPAQUE,
@@ -2328,6 +2314,7 @@ enum rs6000_builtin_type_index
   RS6000_BTI_float,	         /* float_type_node */
   RS6000_BTI_double,	         /* double_type_node */
   RS6000_BTI_void,	         /* void_type_node */
+
   RS6000_BTI_MAX
 };
 
@@ -2376,6 +2363,26 @@ enum rs6000_builtin_type_index
 #define double_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_double])
 #define void_type_internal_node		 (rs6000_builtin_types[RS6000_BTI_void])
 
-extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
-extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
+/* Feature tests for builtin functions.  */
+#define ALTIVEC_BUILTIN_P(FN)						\
+  IN_RANGE ((FN), ALTIVEC_BUILTIN_FIRST, ALTIVEC_BUILTIN_LAST)
+
+#define ALTIVEC_BUILTIN_OVERLOADED_P(FN)				\
+  IN_RANGE ((FN), ALTIVEC_BUILTIN_OVERLOADED_FIRST,			\
+	    ALTIVEC_BUILTIN_OVERLOADED_LAST)
+
+#define VSX_BUILTIN_P(FN) IN_RANGE ((FN), VSX_BUILTIN_FIRST, VSX_BUILTIN_LAST)
+
+#define VSX_BUILTIN_OVERLOADED_P(FN)					\
+  IN_RANGE ((FN), VSX_BUILTIN_OVERLOADED_FIRST, VSX_BUILTIN_OVERLOADED_LAST)
+
+#define OVERLOADED_BUILTIN_P(FN)					\
+  (ALTIVEC_BUILTIN_OVERLOADED_P (FN) || VSX_BUILTIN_OVERLOADED_P (FN))
+
+#define SPE_BUILTIN_P(FN) IN_RANGE ((FN), SPE_BUILTIN_FIRST, SPE_BUILTIN_LAST)
+
+#define PAIRED_BUILTIN_P(FN) 						\
+  IN_RANGE ((FN), PAIRED_BUILTIN_FIRST, PAIRED_BUILTIN_LAST)
 
+#define MISC_BUILTIN_P(FN) 						\
+  IN_RANGE ((FN), MISC_BUILTIN_FIRST, MISC_BUILTIN_LAST)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-23 19:04 [PATCH] Add infrastructure to merge standard builtin enums with backend builtins Michael Meissner
@ 2011-08-24  8:18 ` Mike Stump
  2011-08-24  8:58 ` Paolo Bonzini
  2011-08-24 10:58 ` Richard Guenther
  2 siblings, 0 replies; 10+ messages in thread
From: Mike Stump @ 2011-08-24  8:18 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

On Aug 23, 2011, at 10:29 AM, Michael Meissner wrote:
> This patch growes the bit field that has the builtin function number by one
> bit.

I _use_ 13 bits on my port.  If you do 13, we won't have to change it for 10 years, I promise.  :-)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-23 19:04 [PATCH] Add infrastructure to merge standard builtin enums with backend builtins Michael Meissner
  2011-08-24  8:18 ` Mike Stump
@ 2011-08-24  8:58 ` Paolo Bonzini
  2011-08-24 10:58 ` Richard Guenther
  2 siblings, 0 replies; 10+ messages in thread
From: Paolo Bonzini @ 2011-08-24  8:58 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

On 08/23/2011 07:29 PM, Michael Meissner wrote:
> +	tm_builtin_funcs="$(tm_builtin_funcs) config/rs6000/rs6000-builtin.def"
> +	tm_builtin_funcs="$(tm_builtin_funcs) config/rs6000/rs6000-builtin.def"

These should use braces; build parts are otherwise okay.

Paolo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-23 19:04 [PATCH] Add infrastructure to merge standard builtin enums with backend builtins Michael Meissner
  2011-08-24  8:18 ` Mike Stump
  2011-08-24  8:58 ` Paolo Bonzini
@ 2011-08-24 10:58 ` Richard Guenther
  2011-08-25 22:44   ` Michael Meissner
  2 siblings, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2011-08-24 10:58 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

On Tue, Aug 23, 2011 at 7:29 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> Over the years, it has been a problem for ports like the PowerPC that have
> more builtins than the standard list.  Code that references the built_in_decls
> and implicit_built_in_decls arrays are supposed to check DECL_BUILT_IN_CLASS
> being BUILT_IN_NORMAL first, but every so often code doesn't do this check, and
> it checks random pieces of memory, because the backend builtin function number
> is greater than the number of machine independent builtins.
>
> This patch is an infrastructure patch that lets backends decide to merge their
> builtin enumerations at the end of the standard set of enumerations.  Only the
> PowerPC port is modified with this patch.  If this goes in, the port
> maintainers for the other ports with a lot of builtins (x86, spu, etc.) can
> decide whether to move to this new infrastructure.
>
> This patch growes the bit field that has the builtin function number by one
> bit.  Strictly speaking for the PowerPC, we don't need it just yet, but it
> gives us a margin of safety.  Right now, there are about 730 machine
> independent builtins and 950 PowerPC builtins, which gives us a margin of 350
> more builtins before the field is full, if I didn't grow the size of the
> builtin function bitfield.
>
> When I was documenting the tm-bu-funcs.def file built by the Makefile, I
> noticed there was a FIXME comment asking why tm_p.h existed, so I added an
> explanation.
>
> Originally I wanted to allow the MD file to allow all of the builtins to be
> initialized when the main builtins are setup.  This would have fit into the
> infrastructure, by having MD versions of builtin-attrs.def and
> builtin-types.def.  However, the problem is Fortran doesn't use the C, C++, and
> LTO common builtin infrastructure, but it does want to initialize the target
> builtins via the targetm.init_builtins hook.  So I decided not to include that
> support in this patch.
>
> These are meant to be committed as a single patch, but I have separated the
> patches into a machine indendepent patch, and one that moves the PowerPC to use
> this new infrastructure.
>
> I anticipate there will be additional patches in the powerpc builtin area to
> allow target attributes and pragmas to enable new builtins, but that will be in
> a later patch.  I wanted in this patch to have a fairly minimimal set of
> changes.
>
> I have bootstrapped and done make checks on the PowerPC with no regressions.
> In addition, I have bootstrapped the x86_64 to make sure it continues to work
> for a port that wasn't modified.  Are these patches ok to commit?

This basically would make DECL_BUILT_IN_CLASS no longer necessary
if all targets where converted, right?  (We don't currently have any
BUILT_IN_FRONTEND builtins).  That would sound appealing if this
patch weren't a partial transition ;)

Now for the possible downsides.  How can we reliably distinguish
middle-end from target builtins for purpose of lazy initialization?
Doesn't this complicate the idea of "pluggable" targets, thus
something like a hybrid ppc / spu compiler?  In this light merging
middle-end and target builtin enums and arrays sounds like a step
backward.

What I _do_ like is having common machinery for defining builtins.
Though instead of continuing the .def file way with all the current
warts of ways of adding attributes, etc. to builtins I would have
prefered a genbuiltins.c program that can parse standard C
declarations and generate whatever is necessary to setup the
builtin decls.  Thus, instead of

DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT,
ATTR_CONST_NOTHROW_LEAF_LIST)

have simply

int __builtin_clz (unsigned int) __attribute__((const,nothrow,leaf));

in a header file which genbuiltins.c would parse.  My first idea
when discussing this was a -fgenbuiltins flag to the C frontend
(because that already can do all the parsing ...), but Micha suggested
a parser that can deal with the above is easy enough to "re-implement".

Hm, I guess this pushes back a bit on your patch.  Sorry for that.
If you're not excited to try the above idea, can you split out the
pieces that do the .def file thing for rs6000, keeping the separation
of md and middle-end builtin arrays and enums?

Thanks,
Richard.

> [gcc]
> 2011-08-23  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>        * doc/configfiles.texi (tm_p.h): Document why tm_p.h is needed.
>        (tm-bu-funcs.def): Document the include file that includes the
>        machine dependent builtin functions.
>
>        * tree.h (struct tree_function_decl): Grow function code field by
>        1 bit to allow for machines with lots of builtins.
>
>        * builtins.def (BUILT_IN_NONE): Reserve builtin index 0 so it is
>        not a legitimate builtin.
>        (DEF_BUILTIN_MD): New macro for defining machine dependent
>        builtins.
>        (toplevel): Include tm-bu-funcs.def.
>
>        * configure.ac (tm_builtin_funcs): New autoconf variable to merge
>        backend builtins into the main builtin handling.  Include
>        rs6000-builtin.def on rs6000.
>        * configure: Regenerate.
>        * config.gcc (rs6000*, powerpc*): Ditto.
>
>        * Makefile.in (BUILTINS_DEF): Add support for merging machine
>        dependent builtins at the end of the standard builtins.
>        (BUILTIN_FUNCS_MD): Ditto.
>        (c-family/c-common.o): Ditto.
>        (mostlyclean): Ditto.
>        (tm-bu-funcs.def): New header built that includes machine
>        dependent builtins.
>
>        * config/rs6000/rs6000-protos.h (rs6000_builtin_types): Move here
>        from rs6000.h.  Adjust for merging the rs6000 builtins after the
>        standard builtins.
>        (rs6000_builtin_decls): Ditto.
>
>        * config/rs6000/rs6000-builtin.def (toplevel): Add support for
>        being included in builtins.def to define all rs6000 builtins after
>        the standard builtins.  Delete RS6000_BUILTIN_EQUATE.
>        (RS6000_BUILTIN_FIRST): New macros to mark start and end of
>        various classes of builtins.  Replace existing overload start and
>        end markers.
>        (ALTIVEC_BUILTIN_FIRST): Ditto.
>        (ALTIVEC_BUILTIN_OVERLOADED_FIRST): Ditto.
>        (ALTIVEC_BUILTIN_OVERLOADED_LAST): Ditto.
>        (ALTIVEC_BUILTIN_LAST): Ditto.
>        (SPE_BUILTIN_FIRST): Ditto.
>        (SPE_BUILTIN_LAST): Ditto.
>        (PAIRED_BUILTIN_FIRST): Ditto.
>        (PAIRED_BUILTIN_LAST): Ditto.
>        (VSX_BUILTIN_FIRST): Ditto.
>        (VSX_BUILTIN_OVERLOADED_FIRST): Ditto.
>        (VSX_BUILTIN_OVERLOADED_LAST): Ditto.
>        (VSX_BUILTIN_LAST): Ditto.
>        (RS6000_BUILTIN_LAST): Ditto.
>        (VECTOR_BUILTIN_*): Move so the builtins are in the Altivec
>        range.
>
>        * config/rs6000/rs6000-c.c (struct altivec_builtin_types): Adjust
>        for merging the rs6000 builtins after the standard builtins.
>        (altivec_overloaded_builtins): Ditto.
>
>        * config/rs6000/rs6000.c (rs6000_builtin_decls): Adjust for merging
>        the rs6000 builtins after the standard builtins.
>        (struct builtin_description): Ditto.
>        (builtin_classify): Ditto.
>        (builtin_function_type): Ditto.
>        (rs6000_builtin_decl): Ditto.
>        (enable_mask_for_builtins): Ditto.
>        (rs6000_builtin_vectorized_function): Ditto.
>        (struct builtin_description_predicates): Ditto.
>        (def_builtin): If function is already defined, ignore rather than
>        causing an error.
>        (altivec_expand_builtin): Use OVERLOADED_BUILTIN_P.
>        (altivec_init_builtin): Ditto.
>        (rs6000_init_builtin_types): Split initializing types from the
>        rest of the builtin support.  Add initial steps to making
>        rs6000_init_builtins be called more than one.  Drop testing for
>        VSX for building basic types, just like occurs for Altivec, SPE,
>        etc.
>        (rs6000_init_builtins): Ditto.
>        (rs6000_common_init_builtins): Ditto.
>
>        * config/rs6000/rs6000.h (enum rs6000_builtins): Delete, merge
>        rs6000 builtins to the end of the standard builtins.
>        (rs6000_builtin_types): Move to rs6000-protos.h.
>        (rs6000_builtin_decls): Ditto.
>        (ALTIVEC_BUILTIN_P): New macros mapping builtin function index to
>        machine type.
>        (ALTIVEC_BUILTIN_OVERLOADED_P): Ditto.
>        (VSX_BUILTIN_P): Ditto.
>        (VSX_BUILTIN_OVERLOADED_P): Ditto.
>        (OVERLOADED_BUILTIN_P): Ditto.
>        (SPEC_BUILTIN_P): Ditto.
>        (PAIRED_BUILTIN_P): Ditto.
>        (MISC_BUILTIN_P): Ditto.
>
> [gcc/lto]
> 2011-08-19  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>        * Make-lang.in (lto/lto-lang.o): Adjust dependencies for merging
>        backend builtins into main builtins.
>
>
>
> --
> Michael Meissner, IBM
> 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
> meissner@linux.vnet.ibm.com     fax +1 (978) 399-6899
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-24 10:58 ` Richard Guenther
@ 2011-08-25 22:44   ` Michael Meissner
  2011-08-25 23:12     ` Mike Stump
  2011-08-26 10:03     ` Richard Guenther
  0 siblings, 2 replies; 10+ messages in thread
From: Michael Meissner @ 2011-08-25 22:44 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Wed, Aug 24, 2011 at 11:06:55AM +0200, Richard Guenther wrote:
> This basically would make DECL_BUILT_IN_CLASS no longer necessary
> if all targets where converted, right?  (We don't currently have any
> BUILT_IN_FRONTEND builtins).  That would sound appealing if this
> patch weren't a partial transition ;)

Or we could reduce it to 1 bit if we aren't going to change all of the
backends.

> Now for the possible downsides.  How can we reliably distinguish
> middle-end from target builtins for purpose of lazy initialization?
> Doesn't this complicate the idea of "pluggable" targets, thus
> something like a hybrid ppc / spu compiler?  In this light merging
> middle-end and target builtin enums and arrays sounds like a step
> backward.

If we are willing to pay the storage costs, we could have 1 or 2 bytes for
builtin owner, and 2 bytes for builtin index, and then reserve 0 for standard
builtins and 1 for machine dependent builtins.  However, then you still have
the potential problem that sooner or later somebody else will omit the checks.

We could reserve a fixed range for plugin builtins if you think that is
desirable.

> What I _do_ like is having common machinery for defining builtins.
> Though instead of continuing the .def file way with all the current
> warts of ways of adding attributes, etc. to builtins I would have
> prefered a genbuiltins.c program that can parse standard C
> declarations and generate whatever is necessary to setup the
> builtin decls.  Thus, instead of
> 
> DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT,
> ATTR_CONST_NOTHROW_LEAF_LIST)
> 
> have simply
> 
> int __builtin_clz (unsigned int) __attribute__((const,nothrow,leaf));
> 
> in a header file which genbuiltins.c would parse.  My first idea
> when discussing this was a -fgenbuiltins flag to the C frontend
> (because that already can do all the parsing ...), but Micha suggested
> a parser that can deal with the above is easy enough to "re-implement".

Yes, that is certainly do-able.  My main intention is to see what kind of
infrastructure people wanted before changing all of the ppc builtins.

> Hm, I guess this pushes back a bit on your patch.  Sorry for that.
> If you're not excited to try the above idea, can you split out the
> pieces that do the .def file thing for rs6000, keeping the separation
> of md and middle-end builtin arrays and enums?

I have several goals for the 4.7 time frame:

  1) Make target attribute and pragma enable appropriate machine dependent
     builtins;

  2) Make it less likely we will again be bitten by code that blindly
     references built_in_decl without checking if it is MD or standard;

  3) Make at least the MD builtins created on demand.  It would be nice to do
     the standard builtins as well, but that may somewhat more problematical.
     I do think all references to built_in_decl and implicit_built_in_decl
     should be moved to a macro wrapper.

If we restrict the types and attributes for a C like header file, it shouldn't
be that hard (famous last words).  I would think adding #ifdef also, so:

	#ifdef __ALTIVEC__
	extern vector float __builtin_altivec_vaddfp (vector float, vector
				float) __attribute__ ((...));
	#endif

The backend would need to specify a list of valid #ifdef's and the mapping to
TARGET_<xxx>, and valid extra types with a mapping to the internal type node.

The alternative is something like what Kenney and Mike are doing in their
private port, where they have new syntax in the MD file for builtins.

-- 
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
meissner@linux.vnet.ibm.com	fax +1 (978) 399-6899

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-25 22:44   ` Michael Meissner
@ 2011-08-25 23:12     ` Mike Stump
  2011-08-26 10:03     ` Richard Guenther
  1 sibling, 0 replies; 10+ messages in thread
From: Mike Stump @ 2011-08-25 23:12 UTC (permalink / raw)
  To: Michael Meissner; +Cc: Richard Guenther, gcc-patches, dje.gcc

On Aug 25, 2011, at 1:35 PM, Michael Meissner wrote:
> The alternative is something like what Kenney and Mike are doing in their
> private port, where they have new syntax in the MD file for builtins.

I think the issue is actually largely orthogonal.  In our code, we generate which code is used by a description for the built-in, picking a simple one:

(define_builtin "port_add" "port_add_<type>"
  [
    (define_outputs [(var_operand:T_ALL_DI 0)])
    (define_inputs  [(var_operand:T_ALL_DI 1)
                     (var_operand:T_ALL_DI 2)
                     (var_operand:T_ALL_DI 3)])                                                                                         
    (define_rtl_pattern "port_add_<m_mode>" [0 1 2 3])
    (attributes [pure])
  ]
)

from this, we generate everything needed.  Way under the hood, there is a set of enum values, but, you wouldn't ever see them.  There isn't a one-to-one correspondence as we permit overloading.  We start as 0 and increase, but, we could just as easily start at LAST_MI_BUILTIN+1.  Things like T_ALL_DI as iterators which describe the front-end type to use and how it relates to modes in rtl-land.  T_DI might be long, and T_UDI might be unsigned long, the mode for both is DImode.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-25 22:44   ` Michael Meissner
  2011-08-25 23:12     ` Mike Stump
@ 2011-08-26 10:03     ` Richard Guenther
  2011-08-26 14:41       ` Michael Meissner
  1 sibling, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2011-08-26 10:03 UTC (permalink / raw)
  To: Michael Meissner, Richard Guenther, gcc-patches, dje.gcc

On Thu, Aug 25, 2011 at 10:35 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> On Wed, Aug 24, 2011 at 11:06:55AM +0200, Richard Guenther wrote:
>> This basically would make DECL_BUILT_IN_CLASS no longer necessary
>> if all targets where converted, right?  (We don't currently have any
>> BUILT_IN_FRONTEND builtins).  That would sound appealing if this
>> patch weren't a partial transition ;)
>
> Or we could reduce it to 1 bit if we aren't going to change all of the
> backends.
>
>> Now for the possible downsides.  How can we reliably distinguish
>> middle-end from target builtins for purpose of lazy initialization?
>> Doesn't this complicate the idea of "pluggable" targets, thus
>> something like a hybrid ppc / spu compiler?  In this light merging
>> middle-end and target builtin enums and arrays sounds like a step
>> backward.
>
> If we are willing to pay the storage costs, we could have 1 or 2 bytes for
> builtin owner, and 2 bytes for builtin index, and then reserve 0 for standard
> builtins and 1 for machine dependent builtins.  However, then you still have
> the potential problem that sooner or later somebody else will omit the checks.

I don't think that the issue you only can index BUILT_IN_NORMAL builtins
in built_in_decls is an issue and worth thinking about at all.  It's simply
bugs.

> We could reserve a fixed range for plugin builtins if you think that is
> desirable.

Oh, plugin builtins - I didn't even think about the possibility of having
those ;)

In the end I think we should stick with BUILT_IN_CLASS and maybe
add BUILT_IN_PLUGIN then ;)

>> What I _do_ like is having common machinery for defining builtins.
>> Though instead of continuing the .def file way with all the current
>> warts of ways of adding attributes, etc. to builtins I would have
>> prefered a genbuiltins.c program that can parse standard C
>> declarations and generate whatever is necessary to setup the
>> builtin decls.  Thus, instead of
>>
>> DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT,
>> ATTR_CONST_NOTHROW_LEAF_LIST)
>>
>> have simply
>>
>> int __builtin_clz (unsigned int) __attribute__((const,nothrow,leaf));
>>
>> in a header file which genbuiltins.c would parse.  My first idea
>> when discussing this was a -fgenbuiltins flag to the C frontend
>> (because that already can do all the parsing ...), but Micha suggested
>> a parser that can deal with the above is easy enough to "re-implement".
>
> Yes, that is certainly do-able.  My main intention is to see what kind of
> infrastructure people wanted before changing all of the ppc builtins.

Sure.  I agree that all the duplicated code we have in backends for a
way to create target builtins, defining enums (or not) for them and
having a way to reference them for targetm.builtin_decl (or not) is bad.
But unifying those, or providing common infrastructure for them should
be orthogonal to the issue whether we want to "merge" the builtin
classes or their storage in some way (I think we don't).  It would of
course be nice if the infrastructure to create taget builtins were
generic enough to eventually handle builtin creation in the middle-end
(and the frontends) as well.

>> Hm, I guess this pushes back a bit on your patch.  Sorry for that.
>> If you're not excited to try the above idea, can you split out the
>> pieces that do the .def file thing for rs6000, keeping the separation
>> of md and middle-end builtin arrays and enums?
>
> I have several goals for the 4.7 time frame:
>
>  1) Make target attribute and pragma enable appropriate machine dependent
>     builtins;

That's now something completely new ;)  Why do we need builtins for this?

>  2) Make it less likely we will again be bitten by code that blindly
>     references built_in_decl without checking if it is MD or standard;

I don't think this is important at all.  Proposed solution: transition
builtin decl access to a functional interface:

tree built_in_decl (enum built_in_code)

which when building with C++ will get you warnings if indexed with
a bougs enum type or an integer type.

>  3) Make at least the MD builtins created on demand.  It would be nice to do
>     the standard builtins as well, but that may somewhat more problematical.
>     I do think all references to built_in_decl and implicit_built_in_decl
>     should be moved to a macro wrapper.

To a (inline) function wrapper with the same name, indeed.

> If we restrict the types and attributes for a C like header file, it shouldn't
> be that hard (famous last words).  I would think adding #ifdef also, so:
>
>        #ifdef __ALTIVEC__
>        extern vector float __builtin_altivec_vaddfp (vector float, vector
>                                float) __attribute__ ((...));
>        #endif
>
> The backend would need to specify a list of valid #ifdef's and the mapping to
> TARGET_<xxx>, and valid extra types with a mapping to the internal type node.

Yes.  For the middle-end/frontend stuff we also need a way to specify
the difference between C89 and C99 builtins and GCC internal builtins.

Not sure if I'd use #ifdef like above or simply stick to .def file like
attributions in comments like

/* TARGET(ALTIVEC) */
extern vector float __builtin_altivec_vaddfp (vector float, vector
float) __attribute__ ((...));

/* LANG(C99) */
double cbrt (double, double) __attribute__ ((...));

we also have fancy things like conditionally adding attributes, for example
the ATTR_MATHFN_FPROUNDING stuff.  Using #ifdefs for this would
work, I think there is a special macro defined for -frounding-math.

The idea certainly needs some thoughts, and the target builtins probably
have less feature requirements than the middle-end builtins.def stuff.

The .h file could also serve as a container for builtin documentation.

> The alternative is something like what Kenney and Mike are doing in their
> private port, where they have new syntax in the MD file for builtins.

But are those user-exposed builtins?  Certainly interesting to combine
builtin definition and the instruction it expands to.

Richard.

> --
> Michael Meissner, IBM
> 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
> meissner@linux.vnet.ibm.com     fax +1 (978) 399-6899
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-26 10:03     ` Richard Guenther
@ 2011-08-26 14:41       ` Michael Meissner
  2011-08-27 10:33         ` Mike Stump
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Meissner @ 2011-08-26 14:41 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Fri, Aug 26, 2011 at 10:19:24AM +0200, Richard Guenther wrote:
> On Thu, Aug 25, 2011 at 10:35 PM, Michael Meissner
> <meissner@linux.vnet.ibm.com> wrote:
> > On Wed, Aug 24, 2011 at 11:06:55AM +0200, Richard Guenther wrote:
> >> This basically would make DECL_BUILT_IN_CLASS no longer necessary
> >> if all targets where converted, right?  (We don't currently have any
> >> BUILT_IN_FRONTEND builtins).  That would sound appealing if this
> >> patch weren't a partial transition ;)
> >
> > Or we could reduce it to 1 bit if we aren't going to change all of the
> > backends.
> >
> >> Now for the possible downsides.  How can we reliably distinguish
> >> middle-end from target builtins for purpose of lazy initialization?
> >> Doesn't this complicate the idea of "pluggable" targets, thus
> >> something like a hybrid ppc / spu compiler?  In this light merging
> >> middle-end and target builtin enums and arrays sounds like a step
> >> backward.
> >
> > If we are willing to pay the storage costs, we could have 1 or 2 bytes for
> > builtin owner, and 2 bytes for builtin index, and then reserve 0 for standard
> > builtins and 1 for machine dependent builtins.  However, then you still have
> > the potential problem that sooner or later somebody else will omit the checks.
> 
> I don't think that the issue you only can index BUILT_IN_NORMAL builtins
> in built_in_decls is an issue and worth thinking about at all.  It's simply
> bugs.

I've probably spent about 2-3 weeks total tracking down those bugs in the past,
because they are hard to pin down, but if we don't want to merge the two
numbers it isn't a deal breaker to me.  It was more while I'm playing in the
builtin space, fix the problem.

> > We could reserve a fixed range for plugin builtins if you think that is
> > desirable.
> 
> Oh, plugin builtins - I didn't even think about the possibility of having
> those ;)
> 
> In the end I think we should stick with BUILT_IN_CLASS and maybe
> add BUILT_IN_PLUGIN then ;)

I think if we do this, we should re-use the front end builtin class, and add
methods that front ends can add their builtins to the main list.  Otherwise we
need to grow the class by 1 bit.

> >> What I _do_ like is having common machinery for defining builtins.
> >> Though instead of continuing the .def file way with all the current
> >> warts of ways of adding attributes, etc. to builtins I would have
> >> prefered a genbuiltins.c program that can parse standard C
> >> declarations and generate whatever is necessary to setup the
> >> builtin decls.  Thus, instead of
> >>
> >> DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT,
> >> ATTR_CONST_NOTHROW_LEAF_LIST)
> >>
> >> have simply
> >>
> >> int __builtin_clz (unsigned int) __attribute__((const,nothrow,leaf));
> >>
> >> in a header file which genbuiltins.c would parse.  My first idea
> >> when discussing this was a -fgenbuiltins flag to the C frontend
> >> (because that already can do all the parsing ...), but Micha suggested
> >> a parser that can deal with the above is easy enough to "re-implement".
> >
> > Yes, that is certainly do-able.  My main intention is to see what kind of
> > infrastructure people wanted before changing all of the ppc builtins.
> 
> Sure.  I agree that all the duplicated code we have in backends for a
> way to create target builtins, defining enums (or not) for them and
> having a way to reference them for targetm.builtin_decl (or not) is bad.
> But unifying those, or providing common infrastructure for them should
> be orthogonal to the issue whether we want to "merge" the builtin
> classes or their storage in some way (I think we don't).  It would of
> course be nice if the infrastructure to create taget builtins were
> generic enough to eventually handle builtin creation in the middle-end
> (and the frontends) as well.
> 
> >> Hm, I guess this pushes back a bit on your patch.  Sorry for that.
> >> If you're not excited to try the above idea, can you split out the
> >> pieces that do the .def file thing for rs6000, keeping the separation
> >> of md and middle-end builtin arrays and enums?
> >
> > I have several goals for the 4.7 time frame:
> >
> >  1) Make target attribute and pragma enable appropriate machine dependent
> >     builtins;
> 
> That's now something completely new ;)  Why do we need builtins for this?

I ran out of time when I added target pragma support in 4.6 to enable the
builtins for target functions.  We don't need new builtins, but the ppc backend
needs to enable the builtins that exist when the target is selected, which the
x86 already does.  In the end, I want to be able to do:

	void v4sf_add (float *, float *, float *, size_t)
		__attribute__ ((__ifunc__ ("resolve_v4sf_add")));

	static void v4sf_power7_add (float *, float *, float *, size_t)
		__attribute__ ((__target__ ("cpu=power7")));

	static void v4sf_altivec_add (float *, float *, float *, size_t)
		__attribute__ ((__target__ ("altivec")));

	static void v4sf_generic_add (float *, float *, float *, size_t);

	static void *resolve_v4sf_add (void);

	static void
	v4sf_power7_add (float *a, float *b, float *c, size_t n)
	{
	  size_t n2 = n / 4;
	  size_t n3 = n % 4;
	  while (n2-- > 0)
	    {
	      vector float * v_a = (vector float *)a;
	      vector float * v_b = (vector float *)b;
	      vector float * v_c = (vector float *)c;

	      *v_a = __builtin_vsx_xvaddsp (*v_b, *v_c);
	      a += 4;
	      b += 4;
	      c += 4;
	    }
	  while (n3-- > 0)
	    *a++ = *b++ + *c++;
	}

	static void
	v4sf_altivec_add (float *a, float *b, float *c, size_t n)
	{
	  if (((((size_t)a) & 0xf) == 0)
	      && ((((size_t)b) & 0xf) == 0)
	      && ((((size_t)c) & 0xf) == 0))
	    {
	      size_t n2 = n / 4;
	      n %= 4;
	      while (n2-- > 0)
	        {
		  vector float * v_a = (vector float *)a;
		  vector float * v_b = (vector float *)b;
		  vector float * v_c = (vector float *)c;

		  *v_a = __builtin_altivec_vaddfp (*v_b, *v_c);
		  a += 4;
		  b += 4;
		  c += 4;
		}
	    }
	}

	static void
	v4sf_generic_add (float *a, float *b, float *c, size_t n)
	{
	  while (n-- > 0)
	    *a++ = *b++ + *c++;
	}

	static void *
	resolve_v4sf_add (void)
	{
	  if (running_on_power7 ())
	    return (void *)v4sf_power7_add;
	  else if (running_on_altivec ())
	    return (void *)v4sf_altivec_add;
	  else
	    return (void *)v4sf_generic_add;
	}

Now, in this particular case, the compiler's auto vectorization might be used,
but it is meant to be an example.

> >  2) Make it less likely we will again be bitten by code that blindly
> >     references built_in_decl without checking if it is MD or standard;
> 
> I don't think this is important at all.  Proposed solution: transition
> builtin decl access to a functional interface:
> 
> tree built_in_decl (enum built_in_code)
> 
> which when building with C++ will get you warnings if indexed with
> a bougs enum type or an integer type.

Yep.

> >  3) Make at least the MD builtins created on demand.  It would be nice to do
> >     the standard builtins as well, but that may somewhat more problematical.
> >     I do think all references to built_in_decl and implicit_built_in_decl
> >     should be moved to a macro wrapper.
> 
> To a (inline) function wrapper with the same name, indeed.
> 
> > If we restrict the types and attributes for a C like header file, it shouldn't
> > be that hard (famous last words).  I would think adding #ifdef also, so:
> >
> >        #ifdef __ALTIVEC__
> >        extern vector float __builtin_altivec_vaddfp (vector float, vector
> >                                float) __attribute__ ((...));
> >        #endif
> >
> > The backend would need to specify a list of valid #ifdef's and the mapping to
> > TARGET_<xxx>, and valid extra types with a mapping to the internal type node.
> 
> Yes.  For the middle-end/frontend stuff we also need a way to specify
> the difference between C89 and C99 builtins and GCC internal builtins.
> 
> Not sure if I'd use #ifdef like above or simply stick to .def file like
> attributions in comments like
> 
> /* TARGET(ALTIVEC) */
> extern vector float __builtin_altivec_vaddfp (vector float, vector
> float) __attribute__ ((...));
> 
> /* LANG(C99) */
> double cbrt (double, double) __attribute__ ((...));

This also works.

> we also have fancy things like conditionally adding attributes, for example
> the ATTR_MATHFN_FPROUNDING stuff.  Using #ifdefs for this would
> work, I think there is a special macro defined for -frounding-math.
> 
> The idea certainly needs some thoughts, and the target builtins probably
> have less feature requirements than the middle-end builtins.def stuff.
> 
> The .h file could also serve as a container for builtin documentation.
> 
> > The alternative is something like what Kenney and Mike are doing in their
> > private port, where they have new syntax in the MD file for builtins.
> 
> But are those user-exposed builtins?  Certainly interesting to combine
> builtin definition and the instruction it expands to.

Yes, these are user exposed builtins.  Massive amounts of user exposed builtins
(Mike said he needs 13 bits for the builtin index).  I think it would be better
if Mike comments on this.

-- 
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
meissner@linux.vnet.ibm.com	fax +1 (978) 399-6899

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-26 14:41       ` Michael Meissner
@ 2011-08-27 10:33         ` Mike Stump
  2011-08-27 10:56           ` Richard Guenther
  0 siblings, 1 reply; 10+ messages in thread
From: Mike Stump @ 2011-08-27 10:33 UTC (permalink / raw)
  To: Michael Meissner
  Cc: Richard Guenther, gcc-patches@gcc.gnu.org Patches, David Edelsohn

On Aug 26, 2011, at 7:19 AM, Michael Meissner wrote:
>>> The alternative is something like what Kenney and Mike are doing in their
>>> private port, where they have new syntax in the MD file for builtins.
>> 
>> But are those user-exposed builtins?  Certainly interesting to combine
>> builtin definition and the instruction it expands to.
> 
> Yes, these are user exposed builtins.  Massive amounts of user exposed builtins
> (Mike said he needs 13 bits for the builtin index).  I think it would be better
> if Mike comments on this.

I gave the quick intro yesterday.  You wind up specifying the built-ins that you have, and the generator does things like assign enum values, create a file that appears the builtins into the user name space from the __builtin_ namespace, generate compilation test cases for all the built-ins with all different types they support.  Generate executable testcases to ensure everything works flawlessly.  We have mods to the overload builtin mechanism so that one can do things like:

template <class T>
T foo(T x, T y) {
  x = add(x, y);
  return x;
}

Or, if you perfer the C version:

int fooi(int x, int y) {
  return add(x, y);
}

short foos(short x, short y) {
  return add(x, y);
}

and have it work out just fine when T is instantiated with all the various types that are supported by the hardware, and it works in C.  This permits a nice api for the machine builtins, as you don't have to mangle in types into the builtin-name.  The system is complete enough to handle the needs of anything coming down the pike in the next decade.  It can handle input/output parameters that have register assignments.  It can handle reference parameters (like the input/output parameters, but these are done as values in memory.  The generator builds up _all_ the types one needs, handles all the registration and all the wiring up for codegen.  There is a mechanism to remap arguments going to the rtl generators, so the operand ordering of the builtin doesn't have to match the operand ordering of the md pattern for the semantics that back the builtin.  There is a beefy macro system built into the generator so that you can have nice simple patterns and it is beefier than the iterators one can use today.  So, for example, we have:

(define_special_iterator imath3 [add sub mul])

to define some built-ins that are regular with respect to the operation, but, this isn't a code nor mode iterator, it just iterators the pattern with the string substituted.  For machines with any regularity, the patterns wind up being smaller and easier to maintain.  I'd be happy to answer questions about it.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add infrastructure to merge standard builtin enums with backend builtins
  2011-08-27 10:33         ` Mike Stump
@ 2011-08-27 10:56           ` Richard Guenther
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Guenther @ 2011-08-27 10:56 UTC (permalink / raw)
  To: Mike Stump
  Cc: Michael Meissner, gcc-patches@gcc.gnu.org Patches, David Edelsohn

On Sat, Aug 27, 2011 at 12:12 AM, Mike Stump <mikestump@comcast.net> wrote:
> On Aug 26, 2011, at 7:19 AM, Michael Meissner wrote:
>>>> The alternative is something like what Kenney and Mike are doing in their
>>>> private port, where they have new syntax in the MD file for builtins.
>>>
>>> But are those user-exposed builtins?  Certainly interesting to combine
>>> builtin definition and the instruction it expands to.
>>
>> Yes, these are user exposed builtins.  Massive amounts of user exposed builtins
>> (Mike said he needs 13 bits for the builtin index).  I think it would be better
>> if Mike comments on this.
>
> I gave the quick intro yesterday.  You wind up specifying the built-ins that you have, and the generator does things like assign enum values, create a file that appears the builtins into the user name space from the __builtin_ namespace, generate compilation test cases for all the built-ins with all different types they support.  Generate executable testcases to ensure everything works flawlessly.  We have mods to the overload builtin mechanism so that one can do things like:
>
> template <class T>
> T foo(T x, T y) {
>  x = add(x, y);
>  return x;
> }
>
> Or, if you perfer the C version:
>
> int fooi(int x, int y) {
>  return add(x, y);
> }
>
> short foos(short x, short y) {
>  return add(x, y);
> }
>
> and have it work out just fine when T is instantiated with all the various types that are supported by the hardware, and it works in C.  This permits a nice api for the machine builtins, as you don't have to mangle in types into the builtin-name.  The system is complete enough to handle the needs of anything coming down the pike in the next decade.  It can handle input/output parameters that have register assignments.  It can handle reference parameters (like the input/output parameters, but these are done as values in memory.  The generator builds up _all_ the types one needs, handles all the registration and all the wiring up for codegen.  There is a mechanism to remap arguments going to the rtl generators, so the operand ordering of the builtin doesn't have to match the operand ordering of the md pattern for the semantics that back the builtin.  There is a beefy macro system built into the generator so that you can have nice simple patterns and it is beefier than the iterators one can use today.  So, for example, we have:
>
> (define_special_iterator imath3 [add sub mul])
>
> to define some built-ins that are regular with respect to the operation, but, this isn't a code nor mode iterator, it just iterators the pattern with the string substituted.  For machines with any regularity, the patterns wind up being smaller and easier to maintain.  I'd be happy to answer questions about it.

Maybe you can even post the code somewhere?

Richard.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-08-27  7:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-23 19:04 [PATCH] Add infrastructure to merge standard builtin enums with backend builtins Michael Meissner
2011-08-24  8:18 ` Mike Stump
2011-08-24  8:58 ` Paolo Bonzini
2011-08-24 10:58 ` Richard Guenther
2011-08-25 22:44   ` Michael Meissner
2011-08-25 23:12     ` Mike Stump
2011-08-26 10:03     ` Richard Guenther
2011-08-26 14:41       ` Michael Meissner
2011-08-27 10:33         ` Mike Stump
2011-08-27 10:56           ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).