[gcc(refs/users/wschmidt/heads/builtins4)] rs6000: Update the overloading logic

William Schmidt wschmidt@gcc.gnu.org
Mon Nov 23 21:34:19 GMT 2020


https://gcc.gnu.org/g:adcf0eba77ebeb97a7b1f20d0987cea0b0273b0b

commit adcf0eba77ebeb97a7b1f20d0987cea0b0273b0b
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date:   Mon Nov 23 15:34:00 2020 -0600

    rs6000: Update the overloading logic
    
    2020-11-23  Bill Schmidt  <wschmidt@linux.ibm.com>
    
    gcc/
            * config.gcc (extra_objs): Add rs6000-c.o; otherwise it isn't
            included in the "ar" command and dependency ordering misfires.
            * config/rs6000/altivec.h (vec_mul): Remove.
            (vec_extract): Remove.
            (vec_insert): Remove.
            (vec_splats): Remove.
            (vec_promote): Remove.
            * config/rs6000/rs6000-c.c (altivec_build_new_resolved_builtin):
            Fix argument list.
            (rs6000_new_builtin_type_compatible): New.
            (rs6000_builtin_type_compatible): Rewrite.
            (altivec_build_resolved_builtin): Don't call
            altivec_build_new_resolved_builtin.
            (altivec_build_new_resolved_builtin): New.
            * config/rs6000/rs6000-call.c (rs6000_invalid_new_builtin): New.
            (rs6000_new_builtin_decl): New.
            (rs6000_builtin_decl): Call rs6000_new_builtin_decl.
            * config/rs6000/r6000-gen-builtins.c (max_ovld_args): New
            initialized filescope variable.
            (parse_ovld_entry): Update max_ovld_args.
            (write_decls): Change RS6000_OVLD_* entries to be one per stanza;
            output rs6000_ovld_instances and MAX_OVLD_ARGS; remove hash class
            instances; add ovldrecord and change rs6000_overload_info to use
            it; output declarations of rs6000_new_builtin_is_supported_p and
            rs6000_builtin_decl.
            (write_ovld_static_init): Write static initializer for
            rs6000_overload_info; update initializer for rs6000_instance_info.
            (write_init_bif_table): Remove hashing stuff.
            (write_init_ovld_table): Update initialization for each stanza;
            remove hashing stuff.
            (write_init_file): Remove hashing stuff.
            * config/rs6000/rs6000-overload.def (VEC_ADDE): Update commentary.
            (VEC_EXTRACTM): Alphabetize.
            (VEC_EXTRACT): New empty stanza.
            (VEC_INSERT): Likewise.
            (VEC_MUL): New partial stanza.
            (VEC_PROMOTE): New empty stanza.
            (VEC_SPLATS): Likewise.
            (VEC_STEP): Likewise.
            (VEC_VSIE): Correct builtins mapped to.

Diff:
---
 gcc/config.gcc                          |   1 +
 gcc/config/rs6000/altivec.h             |   6 -
 gcc/config/rs6000/rs6000-c.c            | 425 ++++++++++++++------------------
 gcc/config/rs6000/rs6000-call.c         |  95 ++++++-
 gcc/config/rs6000/rs6000-gen-builtins.c | 180 ++++++--------
 gcc/config/rs6000/rs6000-overload.def   |  77 +++---
 6 files changed, 408 insertions(+), 376 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 8e5a8419f1d..93489914b13 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -511,6 +511,7 @@ powerpc*-*-*)
 	cpu_type=rs6000
 	extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o"
 	extra_objs="${extra_objs} rs6000-call.o rs6000-builtins.o"
+	extra_objs="${extra_objs} rs6000-c.o"
 	extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h"
 	extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h"
 	extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h"
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index cfaf4fe2de8..9ffeb3dda17 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -61,12 +61,6 @@
 /* Functions that are resolved by the backend to one of the
    typed builtins.  */
 #define vec_rlnm(a,b,c) (__builtin_vec_rlnm((a),((c)<<8)|(b)))
-#define vec_mul __builtin_vec_mul
-
-#define vec_extract __builtin_vec_extract
-#define vec_insert __builtin_vec_insert
-#define vec_splats __builtin_vec_splats
-#define vec_promote __builtin_vec_promote
 
 #ifdef __VSX__
 /* VSX additions */
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index c6f0b88ac16..0c00c5881b2 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -39,8 +39,8 @@
 
 
 static tree
-altivec_build_new_resolved_builtin (tree *, int,
-				    const struct altivec_builtin_types *);
+altivec_build_new_resolved_builtin (tree *, int, bifdata *,
+				    rs6000_gen_builtins, rs6000_gen_builtins);
 static tree
 altivec_resolve_new_overloaded_builtin (location_t, tree, void *);
 
@@ -814,20 +814,25 @@ is_float128_p (tree t)
 	      && t == long_double_type_node));
 }
   
-static inline bool
-rs6000_builtin_type_compatible (tree t, int id)
+static bool
+rs6000_new_builtin_type_compatible (tree t, tree u)
 {
-  tree builtin_type;
-  builtin_type = rs6000_builtin_type (id);
   if (t == error_mark_node)
     return false;
-  if (INTEGRAL_TYPE_P (t) && INTEGRAL_TYPE_P (builtin_type))
+  if (INTEGRAL_TYPE_P (t) && INTEGRAL_TYPE_P (u))
     return true;
   else if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
-	   && is_float128_p (t) && is_float128_p (builtin_type))
+	   && is_float128_p (t) && is_float128_p (u))
     return true;
   else
-    return lang_hooks.types_compatible_p (t, builtin_type);
+    return lang_hooks.types_compatible_p (t, u);
+}
+
+static inline bool
+rs6000_builtin_type_compatible (tree t, int id)
+{
+  tree builtin_type = rs6000_builtin_type (id);
+  return rs6000_new_builtin_type_compatible (t, builtin_type);
 }
 
 
@@ -858,9 +863,6 @@ static tree
 altivec_build_resolved_builtin (tree *args, int n,
 				const struct altivec_builtin_types *desc)
 {
-  if (new_builtins_are_live)
-    return altivec_build_new_resolved_builtin (args, n, desc);
-
   tree impl_fndecl = rs6000_builtin_decls[desc->overloaded_code];
   tree ret_type = rs6000_builtin_type (desc->ret_type);
   tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl));
@@ -1933,17 +1935,17 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
    a small exception for vec_{all,any}_{ge,le} predicates. */
 
 static tree
-altivec_build_new_resolved_builtin (tree *args, int n,
-				    const struct altivec_builtin_types *desc)
+altivec_build_new_resolved_builtin (tree *args, int n, bifdata *fndata,
+				    rs6000_gen_builtins bif_id,
+				    rs6000_gen_builtins ovld_id)
 {
-  tree impl_fndecl = rs6000_builtin_decls[desc->overloaded_code];
-  tree ret_type = rs6000_builtin_type (desc->ret_type);
-  tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl));
-  tree arg_type[4];
+  tree ret_type = TREE_VALUE (fndata->fntype);
+  tree argtypes = TREE_CHAIN (fndata->fntype);
+  tree arg_type[MAX_OVLD_ARGS];
+  tree fndecl = rs6000_builtin_decls_x[bif_id];
   tree call;
 
-  int i;
-  for (i = 0; i < n; i++)
+  for (int i = 0; i < n; i++)
     arg_type[i] = TREE_VALUE (argtypes), argtypes = TREE_CHAIN (argtypes);
 
   /* The AltiVec overloading implementation is overall gross, but this
@@ -1957,9 +1959,9 @@ altivec_build_new_resolved_builtin (tree *args, int n,
      argument) is reversed.  Patch the arguments here before building
      the resolved CALL_EXPR.  */
   if (n == 3
-      && desc->code == ALTIVEC_BUILTIN_VEC_VCMPGE_P
-      && desc->overloaded_code != ALTIVEC_BUILTIN_VCMPGEFP_P
-      && desc->overloaded_code != VSX_BUILTIN_XVCMPGEDP_P)
+      && ovld_id == RS6000_OVLD_VEC_CMPGE_P
+      && bif_id != RS6000_BIF_VCMPGEFP_P
+      && bif_id != RS6000_BIF_XVCMPGEDP_P)
     {
       std::swap (args[1], args[2]);
       std::swap (arg_type[1], arg_type[2]);
@@ -1968,28 +1970,32 @@ altivec_build_new_resolved_builtin (tree *args, int n,
 			     build_int_cst (NULL_TREE, 2));
     }
 
+  /* If the number of arguments to an overloaded function increases,
+     we must expand this switch.  */
+  gcc_assert (MAX_OVLD_ARGS <= 4);
+  
   switch (n)
     {
     case 0:
-      call = build_call_expr (impl_fndecl, 0);
+      call = build_call_expr (fndecl, 0);
       break;
     case 1:
-      call = build_call_expr (impl_fndecl, 1,
+      call = build_call_expr (fndecl, 1,
 			      fully_fold_convert (arg_type[0], args[0]));
       break;
     case 2:
-      call = build_call_expr (impl_fndecl, 2,
+      call = build_call_expr (fndecl, 2,
 			      fully_fold_convert (arg_type[0], args[0]),
 			      fully_fold_convert (arg_type[1], args[1]));
       break;
     case 3:
-      call = build_call_expr (impl_fndecl, 3,
+      call = build_call_expr (fndecl, 3,
 			      fully_fold_convert (arg_type[0], args[0]),
 			      fully_fold_convert (arg_type[1], args[1]),
 			      fully_fold_convert (arg_type[2], args[2]));
       break;
     case 4:
-      call = build_call_expr (impl_fndecl, 4,
+      call = build_call_expr (fndecl, 4,
 			      fully_fold_convert (arg_type[0], args[0]),
 			      fully_fold_convert (arg_type[1], args[1]),
 			      fully_fold_convert (arg_type[2], args[2]),
@@ -2010,14 +2016,14 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 {
   vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
   unsigned int nargs = vec_safe_length (arglist);
-  enum rs6000_builtins fcode
-    = (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+  enum rs6000_gen_builtins fcode
+    = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
   tree fnargs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-  tree types[4], args[4];
-  const struct altivec_builtin_types *desc;
+  tree types[MAX_OVLD_ARGS], args[MAX_OVLD_ARGS];
   unsigned int n;
 
-  if (!rs6000_overloaded_builtin_p (fcode))
+  /* Return immediately if this isn't an overload.  */
+  if (fcode <= RS6000_OVLD_NONE)
     return NULL_TREE;
 
   if (TARGET_DEBUG_BUILTIN)
@@ -2025,16 +2031,16 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	     (int)fcode, IDENTIFIER_POINTER (DECL_NAME (fndecl)));
  
   /* vec_lvsl and vec_lvsr are deprecated for use with LE element order.  */
-  if (fcode == ALTIVEC_BUILTIN_VEC_LVSL && !BYTES_BIG_ENDIAN)
+  if (fcode == RS6000_OVLD_VEC_LVSL && !BYTES_BIG_ENDIAN)
     warning (OPT_Wdeprecated,
 	     "%<vec_lvsl%> is deprecated for little endian; use "
 	     "assignment for unaligned loads and stores");
-  else if (fcode == ALTIVEC_BUILTIN_VEC_LVSR && !BYTES_BIG_ENDIAN)
+  else if (fcode == RS6000_OVLD_VEC_LVSR && !BYTES_BIG_ENDIAN)
     warning (OPT_Wdeprecated,
 	     "%<vec_lvsr%> is deprecated for little endian; use "
 	     "assignment for unaligned loads and stores");
 
-  if (fcode == ALTIVEC_BUILTIN_VEC_MUL)
+  if (fcode == RS6000_OVLD_VEC_MUL)
     {
       /* vec_mul needs to be special cased because there are no instructions
 	 for it for the {un}signed char, {un}signed short, and {un}signed int
@@ -2071,13 +2077,13 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	  case E_SFmode:
 	    {
 	      /* For floats use the xvmulsp instruction directly.  */
-	      tree call = rs6000_builtin_decls[VSX_BUILTIN_XVMULSP];
+	      tree call = rs6000_builtin_decls_x[RS6000_BIF_XVMULSP];
 	      return build_call_expr (call, 2, arg0, arg1);
 	    }
 	  case E_DFmode:
 	    {
 	      /* For doubles use the xvmuldp instruction directly.  */
-	      tree call = rs6000_builtin_decls[VSX_BUILTIN_XVMULDP];
+	      tree call = rs6000_builtin_decls_x[RS6000_BIF_XVMULDP];
 	      return build_call_expr (call, 2, arg0, arg1);
 	    }
 	  /* Other types are errors.  */
@@ -2086,7 +2092,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	}
     }
 
-  if (fcode == ALTIVEC_BUILTIN_VEC_CMPNE)
+  if (fcode == RS6000_OVLD_VEC_CMPNE)
     {
       /* vec_cmpne needs to be special cased because there are no instructions
 	 for it (prior to power 9).  */
@@ -2135,8 +2141,8 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 		vec<tree, va_gc> *params = make_tree_vector ();
 		vec_safe_push (params, arg0);
 		vec_safe_push (params, arg1);
-		tree call = altivec_resolve_overloaded_builtin
-		  (loc, rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_CMPEQ],
+		tree call = altivec_resolve_new_overloaded_builtin
+		  (loc, rs6000_builtin_decls_x[RS6000_OVLD_VEC_CMPEQ],
 		   params);
 		/* Use save_expr to ensure that operands used more than once
 		   that may have side effects (like calls) are only evaluated
@@ -2145,8 +2151,8 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 		params = make_tree_vector ();
 		vec_safe_push (params, call);
 		vec_safe_push (params, call);
-		return altivec_resolve_overloaded_builtin
-		  (loc, rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_NOR], params);
+		return altivec_resolve_new_overloaded_builtin
+		  (loc, rs6000_builtin_decls_x[RS6000_OVLD_VEC_NOR], params);
 	      }
 	      /* Other types are errors.  */
 	    default:
@@ -2156,15 +2162,14 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
       /* else, fall through and process the Power9 alternative below */
     }
 
-  if (fcode == ALTIVEC_BUILTIN_VEC_ADDE
-      || fcode == ALTIVEC_BUILTIN_VEC_SUBE)
+  if (fcode == RS6000_OVLD_VEC_ADDE || fcode == RS6000_OVLD_VEC_SUBE)
     {
       /* vec_adde needs to be special cased because there is no instruction
 	  for the {un}signed int version.  */
       if (nargs != 3)
 	{
-	  const char *name = fcode == ALTIVEC_BUILTIN_VEC_ADDE ?
-	    "vec_adde": "vec_sube";
+	  const char *name
+	    = fcode == RS6000_OVLD_VEC_ADDE ? "vec_adde": "vec_sube";
 	  error ("builtin %qs only accepts 3 arguments", name);
 	  return error_mark_node;
 	}
@@ -2199,14 +2204,15 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	      vec_safe_push (params, arg0);
 	      vec_safe_push (params, arg1);
 
-	      if (fcode == ALTIVEC_BUILTIN_VEC_ADDE)
-		add_sub_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD];
+	      if (fcode == RS6000_OVLD_VEC_ADDE)
+		add_sub_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_ADD];
 	      else
-		add_sub_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_SUB];
+		add_sub_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_SUB];
 
-	      tree call = altivec_resolve_overloaded_builtin (loc,
-							      add_sub_builtin,
-							      params);
+	      tree call
+		= altivec_resolve_new_overloaded_builtin (loc,
+							  add_sub_builtin,
+							  params);
 	      tree const1 = build_int_cstu (TREE_TYPE (arg0_type), 1);
 	      tree ones_vector = build_vector_from_val (arg0_type, const1);
 	      tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR, arg0_type,
@@ -2214,22 +2220,14 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	      params = make_tree_vector ();
 	      vec_safe_push (params, call);
 	      vec_safe_push (params, and_expr);
-	      return altivec_resolve_overloaded_builtin (loc, add_sub_builtin,
-							 params);
+	      return altivec_resolve_new_overloaded_builtin (loc,
+							     add_sub_builtin,
+							     params);
 	    }
-	  /* For {un}signed __int128s use the vaddeuqm instruction
-		directly.  */
+	  /* For {un}signed __int128s use the vaddeuqm/vsubeuqm instruction
+	     directly.  This is done by the normal processing.  */
 	  case E_TImode:
 	    {
-	       tree bii;
-
-	       if (fcode == ALTIVEC_BUILTIN_VEC_ADDE)
-		 bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDEUQM];
-
-	       else
-		 bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VSUBEUQM];
-
-	       return altivec_resolve_overloaded_builtin (loc, bii, arglist);
 	    }
 
 	  /* Types other than {un}signed int and {un}signed __int128
@@ -2239,14 +2237,13 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	}
     }
 
-  if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC
-      || fcode == ALTIVEC_BUILTIN_VEC_SUBEC)
+  if (fcode == RS6000_OVLD_VEC_ADDEC || fcode == RS6000_OVLD_VEC_SUBEC)
     {
       /* vec_addec and vec_subec needs to be special cased because there is
 	 no instruction for the {un}signed int version.  */
       if (nargs != 3)
 	{
-	  const char *name = fcode == ALTIVEC_BUILTIN_VEC_ADDEC ?
+	  const char *name = fcode == RS6000_OVLD_VEC_ADDEC ?
 	    "vec_addec": "vec_subec";
 	  error ("builtin %qs only accepts 3 arguments", name);
 	  return error_mark_node;
@@ -2288,25 +2285,27 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	    vec_safe_push (params, arg0);
 	    vec_safe_push (params, arg1);
 
-	    if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
-	      as_c_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADDC];
+	    if (fcode == RS6000_OVLD_VEC_ADDEC)
+	      as_c_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_ADDC];
 	    else
-	      as_c_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_SUBC];
+	      as_c_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_SUBC];
 
-	    tree call1 = altivec_resolve_overloaded_builtin (loc, as_c_builtin,
-							     params);
+	    tree call1 = altivec_resolve_new_overloaded_builtin (loc,
+								 as_c_builtin,
+								 params);
 	    params = make_tree_vector ();
 	    vec_safe_push (params, arg0);
 	    vec_safe_push (params, arg1);
 
 
-	    if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
-	      as_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD];
+	    if (fcode == RS6000_OVLD_VEC_ADDEC)
+	      as_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_ADD];
 	    else
-	      as_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_SUB];
+	      as_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_SUB];
 
-	    tree call2 = altivec_resolve_overloaded_builtin (loc, as_builtin,
-							     params);
+	    tree call2 = altivec_resolve_new_overloaded_builtin (loc,
+								 as_builtin,
+								 params);
 	    tree const1 = build_int_cstu (TREE_TYPE (arg0_type), 1);
 	    tree ones_vector = build_vector_from_val (arg0_type, const1);
 	    tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR, arg0_type,
@@ -2314,28 +2313,19 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	    params = make_tree_vector ();
 	    vec_safe_push (params, call2);
 	    vec_safe_push (params, and_expr);
-	    call2 = altivec_resolve_overloaded_builtin (loc, as_c_builtin,
-							params);
+	    call2 = altivec_resolve_new_overloaded_builtin (loc, as_c_builtin,
+							    params);
 	    params = make_tree_vector ();
 	    vec_safe_push (params, call1);
 	    vec_safe_push (params, call2);
-	    tree or_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_OR];
-	    return altivec_resolve_overloaded_builtin (loc, or_builtin,
-						       params);
+	    tree or_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_OR];
+	    return altivec_resolve_new_overloaded_builtin (loc, or_builtin,
+							   params);
 	    }
 	  /* For {un}signed __int128s use the vaddecuq/vsubbecuq
-	     instructions.  */
+	     instructions.  This occurs through normal processing.  */
 	  case E_TImode:
 	    {
-	       tree bii;
-
-	       if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
-		 bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDECUQ];
-
-	       else
-		 bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VSUBECUQ];
-
-	       return altivec_resolve_overloaded_builtin (loc, bii, arglist);
 	    }
 	  /* Types other than {un}signed int and {un}signed __int128
 		are errors.  */
@@ -2345,28 +2335,28 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
     }
 
   /* For now treat vec_splats and vec_promote as the same.  */
-  if (fcode == ALTIVEC_BUILTIN_VEC_SPLATS
-      || fcode == ALTIVEC_BUILTIN_VEC_PROMOTE)
+  if (fcode == RS6000_OVLD_VEC_SPLATS || fcode == RS6000_OVLD_VEC_PROMOTE)
     {
       tree type, arg;
       int size;
       int i;
       bool unsigned_p;
       vec<constructor_elt, va_gc> *vec;
-      const char *name = fcode == ALTIVEC_BUILTIN_VEC_SPLATS ? "vec_splats": "vec_promote";
+      const char *name
+	= fcode == RS6000_OVLD_VEC_SPLATS ? "vec_splats": "vec_promote";
 
-      if (fcode == ALTIVEC_BUILTIN_VEC_SPLATS && nargs != 1)
+      if (fcode == RS6000_OVLD_VEC_SPLATS && nargs != 1)
 	{
 	  error ("builtin %qs only accepts 1 argument", name);
 	  return error_mark_node;
 	}
-      if (fcode == ALTIVEC_BUILTIN_VEC_PROMOTE && nargs != 2)
+      if (fcode == RS6000_OVLD_VEC_PROMOTE && nargs != 2)
 	{
 	  error ("builtin %qs only accepts 2 arguments", name);
 	  return error_mark_node;
 	}
       /* Ignore promote's element argument.  */
-      if (fcode == ALTIVEC_BUILTIN_VEC_PROMOTE
+      if (fcode == RS6000_OVLD_VEC_PROMOTE
 	  && !INTEGRAL_TYPE_P (TREE_TYPE ((*arglist)[1])))
 	goto bad;
 
@@ -2415,7 +2405,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 
   /* For now use pointer tricks to do the extraction, unless we are on VSX
      extracting a double from a constant offset.  */
-  if (fcode == ALTIVEC_BUILTIN_VEC_EXTRACT)
+  if (fcode == RS6000_OVLD_VEC_EXTRACT)
     {
       tree arg1;
       tree arg1_type;
@@ -2466,34 +2456,34 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 		  break;
 
 		case E_V1TImode:
-		  call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V1TI];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V1TI];
 		  break;
 
 		case E_V2DFmode:
-		  call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V2DF];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DF];
 		  break;
 
 		case E_V2DImode:
-		  call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V2DI];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DI];
 		  break;
 
 		case E_V4SFmode:
-		  call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V4SF];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SF];
 		  break;
 
 		case E_V4SImode:
 		  if (TARGET_DIRECT_MOVE_64BIT)
-		    call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V4SI];
+		    call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SI];
 		  break;
 
 		case E_V8HImode:
 		  if (TARGET_DIRECT_MOVE_64BIT)
-		    call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V8HI];
+		    call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V8HI];
 		  break;
 
 		case E_V16QImode:
 		  if (TARGET_DIRECT_MOVE_64BIT)
-		    call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V16QI];
+		    call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V16QI];
 		  break;
 		}
 	    }
@@ -2508,27 +2498,27 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 		  break;
 
 		case E_V2DFmode:
-		  call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V2DF];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DF];
 		  break;
 
 		case E_V2DImode:
-		  call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V2DI];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DI];
 		  break;
 
 		case E_V4SFmode:
-		  call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V4SF];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SF];
 		  break;
 
 		case E_V4SImode:
-		  call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V4SI];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SI];
 		  break;
 
 		case E_V8HImode:
-		  call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V8HI];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V8HI];
 		  break;
 
 		case E_V16QImode:
-		  call = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_EXT_V16QI];
+		  call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V16QI];
 		  break;
 		}
 	    }
@@ -2582,7 +2572,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	 downstream in fold_build_cleanup_point_expr () it will get a
 	 CLEANUP_POINT_EXPR.  If it does not we can run into an ICE
 	 later in gimplify_cleanup_point_expr ().  Potentially this
-	 causes missed optimization because the actually is no side
+	 causes missed optimization because there actually is no side
 	 effect.  */
       if (c_dialect_cxx ())
 	TREE_SIDE_EFFECTS (stmt) = 1;
@@ -2592,7 +2582,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 
   /* For now use pointer tricks to do the insertion, unless we are on VSX
      inserting a double to a constant offset..  */
-  if (fcode == ALTIVEC_BUILTIN_VEC_INSERT)
+  if (fcode == RS6000_OVLD_VEC_INSERT)
     {
       tree arg0;
       tree arg1;
@@ -2631,9 +2621,9 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 
 	  arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);
 	  if (mode == V2DFmode)
-	    call = rs6000_builtin_decls[VSX_BUILTIN_VEC_SET_V2DF];
+	    call = rs6000_builtin_decls_x[RS6000_BIF_VEC_SET_V2DF];
 	  else if (mode == V2DImode)
-	    call = rs6000_builtin_decls[VSX_BUILTIN_VEC_SET_V2DI];
+	    call = rs6000_builtin_decls_x[RS6000_BIF_VEC_SET_V2DI];
 
 	  /* Note, __builtin_vec_insert_<xxx> has vector and scalar types
 	     reversed.  */
@@ -2643,7 +2633,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
       else if (mode == V1TImode && VECTOR_UNIT_VSX_P (mode)
 	       && TREE_CODE (arg2) == INTEGER_CST)
 	{
-	  tree call = rs6000_builtin_decls[VSX_BUILTIN_VEC_SET_V1TI];
+	  tree call = rs6000_builtin_decls_x[RS6000_BIF_VEC_SET_V1TI];
 	  wide_int selector = wi::zero(32);
 
 	  arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);
@@ -2706,7 +2696,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
       if (arg == error_mark_node)
 	return error_mark_node;
 
-      if (n >= 4)
+      if (n >= MAX_OVLD_ARGS)
         abort ();
 
       arg = default_conversion (arg);
@@ -2740,9 +2730,9 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	  arg = fold_convert (type, arg);
 	}
 
-      /* For P9V_BUILTIN_VEC_LXVL, convert any const * to its non constant
+      /* For RS6000_OVLD_VEC_LXVL, convert any const * to its non constant
 	 equivalent to simplify the overload matching below.  */
-      if (fcode == P9V_BUILTIN_VEC_LXVL)
+      if (fcode == RS6000_OVLD_VEC_LXVL)
 	{
 	  if (POINTER_TYPE_P (type)
 	      && TYPE_READONLY (TREE_TYPE (type)))
@@ -2765,7 +2755,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
   if (n == 0)
     abort ();
 
-  if (fcode == ALTIVEC_BUILTIN_VEC_STEP)
+  if (fcode == RS6000_OVLD_VEC_STEP)
     {
       if (TREE_CODE (types[0]) != VECTOR_TYPE)
 	goto bad;
@@ -2775,19 +2765,18 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 
   {
     bool unsupported_builtin = false;
-    enum rs6000_builtins overloaded_code;
+    enum rs6000_gen_builtins overloaded_code;
     tree result = NULL;
-    for (desc = altivec_overloaded_builtins;
-	 desc->code && desc->code != fcode; desc++)
-      continue;
+    ovlddata *instance = rs6000_overload_info[fcode].first_instance;
+    gcc_assert (instance != NULL);
 
-    /* Need to special case __builtin_cmp because the overloaded forms
+    /* Need to special case __builtin_cmpb because the overloaded forms
        of this function take (unsigned int, unsigned int) or (unsigned
        long long int, unsigned long long int).  Since C conventions
        allow the respective argument types to be implicitly coerced into
        each other, the default handling does not provide adequate
        discrimination between the desired forms of the function.  */
-    if (fcode == P6_OV_BUILTIN_CMPB)
+    if (fcode == RS6000_OVLD_SCAL_CMPB)
       {
 	machine_mode arg1_mode = TYPE_MODE (types[0]);
 	machine_mode arg2_mode = TYPE_MODE (types[1]);
@@ -2804,38 +2793,38 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	    || (GET_MODE_PRECISION (arg2_mode) > 32))
 	  {
 	    /* Assure all argument and result types are compatible with
-	       the built-in function represented by P6_BUILTIN_CMPB.  */
-	    overloaded_code = P6_BUILTIN_CMPB;
+	       the built-in function represented by RS6000_BIF_CMPB.  */
+	    overloaded_code = RS6000_BIF_CMPB;
 	  }
 	else
 	  {
 	    /* Assure all argument and result types are compatible with
-	       the built-in function represented by P6_BUILTIN_CMPB_32.  */
-	    overloaded_code = P6_BUILTIN_CMPB_32;
+	       the built-in function represented by RS6000_BIF_CMPB_32.  */
+	    overloaded_code = RS6000_BIF_CMPB_32;
 	  }
 
-	while (desc->code && desc->code == fcode
-	       && desc->overloaded_code != overloaded_code)
-	  desc++;
+	while (instance && instance->bifid != overloaded_code)
+	  instance = instance->next;
 
-	if (desc->code && (desc->code == fcode)
-	    && rs6000_builtin_type_compatible (types[0], desc->op1)
-	    && rs6000_builtin_type_compatible (types[1], desc->op2))
+	gcc_assert (instance != NULL);
+	bifdata *fndata = &rs6000_builtin_info_x[instance->bifid];
+	tree fntype = fndata->fntype;
+	tree parmtype0 = TREE_VALUE (TREE_CHAIN (fntype));
+	tree parmtype1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (fntype)));
+
+	if (rs6000_new_builtin_type_compatible (types[0], parmtype0)
+	    && rs6000_new_builtin_type_compatible (types[1], parmtype1))
 	  {
-	    if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
-	      {
-		result = altivec_build_resolved_builtin (args, n, desc);
-		/* overloaded_code is set above */
-		if (!rs6000_builtin_is_supported_p (overloaded_code))
-		  unsupported_builtin = true;
-		else
-		  return result;
-	      }
+	    if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+		&& rs6000_new_builtin_is_supported_p (instance->bifid))
+	      return altivec_build_new_resolved_builtin (args, n, fndata,
+							 instance->bifid,
+							 fcode);
 	    else
 	      unsupported_builtin = true;
 	  }
       }
-    else if (fcode == P9V_BUILTIN_VEC_VSIEDP)
+    else if (fcode == RS6000_OVLD_VEC_VSIE)
       {
 	machine_mode arg1_mode = TYPE_MODE (types[0]);
 
@@ -2854,9 +2843,9 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	       that expects __ieee128 argument.  Otherwise, expect
 	       __int128 argument.  */
 	    if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT)
-	      overloaded_code = P9V_BUILTIN_VSIEQPF;
+	      overloaded_code = RS6000_BIF_VSIEQPF;
 	    else
-	      overloaded_code = P9V_BUILTIN_VSIEQP;
+	      overloaded_code = RS6000_BIF_VSIEQP;
 	  }
 	else
 	  {
@@ -2864,116 +2853,78 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
 	       that expects double argument.  Otherwise, expect
 	       long long int argument.  */
 	    if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT)
-	      overloaded_code = P9V_BUILTIN_VSIEDPF;
+	      overloaded_code = RS6000_BIF_VSIEDPF;
 	    else
-	      overloaded_code = P9V_BUILTIN_VSIEDP;
+	      overloaded_code = RS6000_BIF_VSIEDP;
 	  }
-	while (desc->code && desc->code == fcode
-	       && desc->overloaded_code != overloaded_code)
-	  desc++;
 
-	if (desc->code && (desc->code == fcode)
-	    && rs6000_builtin_type_compatible (types[0], desc->op1)
-	    && rs6000_builtin_type_compatible (types[1], desc->op2))
+	while (instance && instance->bifid != overloaded_code)
+	  instance = instance->next;
+
+	gcc_assert (instance != NULL);
+	bifdata *fndata = &rs6000_builtin_info_x[instance->bifid];
+	tree fntype = fndata->fntype;
+	tree parmtype0 = TREE_VALUE (TREE_CHAIN (fntype));
+	tree parmtype1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (fntype)));
+
+	if (rs6000_new_builtin_type_compatible (types[0], parmtype0)
+	    && rs6000_new_builtin_type_compatible (types[1], parmtype1))
 	  {
-	    if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
-	      {
-		result = altivec_build_resolved_builtin (args, n, desc);
-		/* overloaded_code is set above.  */
-		if (!rs6000_builtin_is_supported_p (overloaded_code))
-		  unsupported_builtin = true;
-		else
-		  return result;
-	      }
+	    if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+		&& rs6000_new_builtin_is_supported_p (instance->bifid))
+	      return altivec_build_new_resolved_builtin (args, n, fndata,
+							 instance->bifid,
+							 fcode);
 	    else
 	      unsupported_builtin = true;
 	  }
       }
-    else if ((fcode == P10_BUILTIN_VEC_XXEVAL)
-	    || (fcode == P10V_BUILTIN_VXXPERMX))
+    else
       {
-	signed char op3_type;
-
-	/* Need to special case P10_BUILTIN_VEC_XXEVAL and
-	   P10V_BUILTIN_VXXPERMX because they take 4 arguments and the
-	   existing infrastructure only handles three.  */
-	if (nargs != 4)
-	  {
-	    const char *name = fcode == P10_BUILTIN_VEC_XXEVAL ?
-	      "__builtin_vec_xxeval":"__builtin_vec_xxpermx";
-
-	    error ("builtin %qs requires 4 arguments", name);
-	    return error_mark_node;
-	  }
-
-	for ( ; desc->code == fcode; desc++)
+	for (; instance != NULL; instance = instance->next)
 	  {
-	    if (fcode == P10_BUILTIN_VEC_XXEVAL)
-	      op3_type = desc->op3;
-	    else  /* P10V_BUILTIN_VXXPERMX */
-	      op3_type = RS6000_BTI_V16QI;
+	    bool mismatch = false;
+	    bifdata *fndata = &rs6000_builtin_info_x[instance->bifid];
+	    tree nextparm = TREE_CHAIN (fndata->fntype);
 
-	    if (rs6000_builtin_type_compatible (types[0], desc->op1)
-		&& rs6000_builtin_type_compatible (types[1], desc->op2)
-		&& rs6000_builtin_type_compatible (types[2], desc->op3)
-		&& rs6000_builtin_type_compatible (types[2], op3_type)
-		&& rs6000_builtin_type_compatible (types[3],
-						   RS6000_BTI_UINTSI))
+	    for (int arg_i = 0;
+		 arg_i < fndata->nargs && nextparm != NULL;
+		 arg_i++)
 	      {
-		if (rs6000_builtin_decls[desc->overloaded_code] == NULL_TREE)
-		  unsupported_builtin = true;
-		else
+		tree parmtype = TREE_VALUE (nextparm);
+		if (!rs6000_new_builtin_type_compatible (types[arg_i],
+							 parmtype))
 		  {
-		    result = altivec_build_resolved_builtin (args, n, desc);
-		    if (rs6000_builtin_is_supported_p (desc->overloaded_code))
-		      return result;
-		    /* Allow loop to continue in case a different
-		       definition is supported.  */
-		    overloaded_code = desc->overloaded_code;
-		    unsupported_builtin = true;
+		    mismatch = true;
+		    break;
 		  }
+		nextparm = TREE_CHAIN (nextparm);
 	      }
-	  }
-      }
-    else
-      {
-	/* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in
-	   the opX fields.  */
-	for (; desc->code == fcode; desc++)
-	  {
-	    if ((desc->op1 == RS6000_BTI_NOT_OPAQUE
-		 || rs6000_builtin_type_compatible (types[0], desc->op1))
-		&& (desc->op2 == RS6000_BTI_NOT_OPAQUE
-		    || rs6000_builtin_type_compatible (types[1], desc->op2))
-		&& (desc->op3 == RS6000_BTI_NOT_OPAQUE
-		    || rs6000_builtin_type_compatible (types[2], desc->op3)))
+
+	    if (mismatch)
+	      continue;
+
+	    if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+		&& rs6000_new_builtin_is_supported_p (instance->bifid))
+	      return altivec_build_new_resolved_builtin (args, n, fndata,
+							 instance->bifid,
+							 fcode);
+	    else
 	      {
-		if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
-		  {
-		    result = altivec_build_resolved_builtin (args, n, desc);
-		    if (!rs6000_builtin_is_supported_p (desc->overloaded_code))
-		      {
-			/* Allow loop to continue in case a different
-			   definition is supported.  */
-			overloaded_code = desc->overloaded_code;
-			unsupported_builtin = true;
-		      }
-		    else
-		      return result;
-		  }
-		else
-		  unsupported_builtin = true;
+		unsupported_builtin = true;
+		break;
 	      }
 	  }
+	gcc_assert (unsupported_builtin);
       }
 
     if (unsupported_builtin)
       {
-	const char *name = rs6000_overloaded_builtin_name (fcode);
+	const char *name = rs6000_overload_info[fcode].ovld_name;
 	if (result != NULL)
 	  {
 	    const char *internal_name
-	      = rs6000_overloaded_builtin_name (overloaded_code);
+	      = rs6000_builtin_info_x[instance->bifid].bifname;
 	    /* An error message making reference to the name of the
 	       non-overloaded function has already been issued.  Add
 	       clarification of the previous message.  */
@@ -2990,7 +2941,7 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
   }
  bad:
   {
-    const char *name = rs6000_overloaded_builtin_name (fcode);
+    const char *name = rs6000_overload_info[fcode].ovld_name;
     error ("invalid parameter combination for AltiVec intrinsic %qs", name);
     return error_mark_node;
   }
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 6b682d733ae..2a4dccf9567 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -11821,6 +11821,80 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
     error ("%qs is not supported with the current options", name);
 }
 
+/* Raise an error message for a builtin function that is called without the
+   appropriate target options being set.  */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+  size_t uns_fncode = (size_t) fncode;
+  const char *name = rs6000_builtin_info_x[uns_fncode].bifname;
+
+  switch (rs6000_builtin_info_x[uns_fncode].enable)
+    {
+    case ENB_P5:
+      error ("%qs requires the %qs option", name, "-mcpu=power5");
+      break;
+    case ENB_P6:
+      error ("%qs requires the %qs option", name, "-mcpu=power6");
+      break;
+    case ENB_ALTIVEC:
+      error ("%qs requires the %qs option", name, "-maltivec");
+      break;
+    case ENB_CELL:
+      error ("%qs is only valid for the cell processor", name);
+      break;
+    case ENB_VSX:
+      error ("%qs requires the %qs option", name, "-mvsx");
+      break;
+    case ENB_P7:
+      error ("%qs requires the %qs option", name, "-mcpu=power7");
+      break;
+    case ENB_P7_64:
+      error ("%qs requires the %qs option and either the %qs or %qs option",
+	     name, "-mcpu=power7", "-m64", "-mpowerpc64");
+      break;
+    case ENB_P8:
+      error ("%qs requires the %qs option", name, "-mcpu=power8");
+      break;
+    case ENB_P8V:
+      error ("%qs requires the %qs option", name, "-mpower8-vector");
+      break;
+    case ENB_P9:
+      error ("%qs requires the %qs option", name, "-mcpu=power9");
+      break;
+    case ENB_P9_64:
+      error ("%qs requires the %qs option and either the %qs or %qs option",
+	     name, "-mcpu=power9", "-m64", "-mpowerpc64");
+      break;
+    case ENB_P9V:
+      error ("%qs requires the %qs option", name, "-mpower9-vector");
+      break;
+    case ENB_IEEE128_HW:
+      error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name);
+      break;
+    case ENB_DFP:
+      error ("%qs requires the %qs option", name, "-mhard-dfp");
+      break;
+    case ENB_CRYPTO:
+      error ("%qs requires the %qs option", name, "-mcrypto");
+      break;
+    case ENB_HTM:
+      error ("%qs requires the %qs option", name, "-mhtm");
+      break;
+    case ENB_P10:
+      error ("%qs requires the %qs option", name, "-mcpu=power10");
+      break;
+    case ENB_MMA:
+      error ("%qs requires the %qs option", name, "-mmma");
+      break;
+    default:
+    case ENB_ALWAYS:
+      gcc_unreachable ();
+    };
+  gcc_unreachable ();
+}
+
 /* Target hook for early folding of built-ins, shamelessly stolen
    from ia64.c.  */
 
@@ -15913,12 +15987,31 @@ rs6000_init_builtins (void)
 #endif
 }
 
+static tree
+rs6000_new_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
+{
+  rs6000_gen_builtins fcode = (rs6000_gen_builtins) code;
+
+  if (fcode >= RS6000_OVLD_MAX)
+    return error_mark_node;
+
+  if (!rs6000_new_builtin_is_supported_p (fcode))
+    {
+      rs6000_invalid_new_builtin (fcode);
+      return error_mark_node;
+    }
+
+  return rs6000_builtin_decls_x[code];
+}
+
 /* Returns the rs6000 builtin decl for CODE.  */
-/* #### TODO: Rewrite this.  */
 
 tree
 rs6000_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
 {
+  if (new_builtins_are_live)
+    return rs6000_new_builtin_decl (code, initialize_p);
+  
   HOST_WIDE_INT fnmask;
 
   if (code >= RS6000_BUILTIN_COUNT)
diff --git a/gcc/config/rs6000/rs6000-gen-builtins.c b/gcc/config/rs6000/rs6000-gen-builtins.c
index c7f405e33fd..6fe3b929597 100644
--- a/gcc/config/rs6000/rs6000-gen-builtins.c
+++ b/gcc/config/rs6000/rs6000-gen-builtins.c
@@ -408,6 +408,7 @@ struct ovlddata {
 static ovlddata ovlds[MAXOVLDS];
 static int num_ovlds;
 static int curr_ovld;
+static int max_ovld_args = 0;
 
 /* Exit codes for the shell.  */
 enum exit_codes {
@@ -1899,6 +1900,9 @@ parse_ovld_entry ()
   if (parse_prototype (&ovlds[curr_ovld].proto) == PC_PARSEFAIL)
     return PC_PARSEFAIL;
 
+  if (ovlds[curr_ovld].proto.nargs > max_ovld_args)
+    max_ovld_args = ovlds[curr_ovld].proto.nargs;
+
   /* Build a function type descriptor identifier from the return type
      and argument types, and store it if it does not already exist.  */
   ovlds[curr_ovld].fndecl = construct_fntype_id (&ovlds[curr_ovld].proto);
@@ -2110,13 +2114,21 @@ write_decls ()
     fprintf (header_file, "  RS6000_BIF_%s,\n", bifs[bif_order[i]].idname);
   fprintf (header_file, "  RS6000_BIF_MAX,\n");
   fprintf (header_file, "  RS6000_OVLD_NONE,\n");
-  for (int i = 0; i < num_ovlds; i++)
-    fprintf (header_file, "  RS6000_OVLD_%s,\n", ovlds[i].ovld_id_name);
+  for (int i = 0; i < num_ovld_stanzas; i++)
+    fprintf (header_file, "  RS6000_OVLD_%s,\n", ovld_stanzas[i].stanza_id);
   fprintf (header_file, "  RS6000_OVLD_MAX\n};\n\n");
 
   fprintf (header_file,
 	   "extern tree rs6000_builtin_decls_x[RS6000_OVLD_MAX];\n\n");
 
+  fprintf (header_file,
+	   "enum rs6000_ovld_instances\n{\n  RS6000_INST_NONE,\n");
+  for (int i = 0; i <= curr_ovld; i++)
+    fprintf (header_file, "  RS6000_INST_%s,\n", ovlds[i].ovld_id_name);
+  fprintf (header_file, "  RS6000_INST_MAX\n};\n\n");
+
+  fprintf (header_file, "#define MAX_OVLD_ARGS %d\n", max_ovld_args);
+
   fprintf (header_file, "enum restriction {\n");
   fprintf (header_file, "  RES_NONE,\n");
   fprintf (header_file, "  RES_BITS,\n");
@@ -2228,16 +2240,6 @@ write_decls ()
      be removed as we progress.  */
   fprintf (header_file, "extern bifdata rs6000_builtin_info_x[];\n\n");
 
-  fprintf (header_file,
-	   "struct rs6000_bif_hasher : nofree_ptr_hash<bifdata>\n");
-  fprintf (header_file, "{\n");
-  fprintf (header_file, "  typedef const char *compare_type;\n\n");
-  fprintf (header_file, "  static hashval_t hash (bifdata *);\n");
-  fprintf (header_file, "  static bool equal (bifdata *, const char *);\n");
-  fprintf (header_file, "};\n\n");
-
-  fprintf (header_file, "extern hash_table<rs6000_bif_hasher> bif_hash;\n\n");
-
   fprintf (header_file, "struct ovlddata\n");
   fprintf (header_file, "{\n");
   fprintf (header_file, "  const char *bifname;\n");
@@ -2246,20 +2248,22 @@ write_decls ()
   fprintf (header_file, "  ovlddata *next;\n");
   fprintf (header_file, "};\n\n");
 
-  fprintf (header_file, "extern ovlddata rs6000_overload_info[];\n\n");
-
-  fprintf (header_file,
-	   "struct rs6000_ovld_hasher : nofree_ptr_hash<ovlddata>\n");
+  fprintf (header_file, "struct ovldrecord\n");
   fprintf (header_file, "{\n");
-  fprintf (header_file, "  typedef const char *compare_type;\n\n");
-  fprintf (header_file, "  static hashval_t hash (ovlddata *);\n");
-  fprintf (header_file, "  static bool equal (ovlddata *, const char *);\n");
+  fprintf (header_file, "  const char *ovld_name;\n");
+  fprintf (header_file, "  ovlddata *first_instance;\n");
   fprintf (header_file, "};\n\n");
 
-  fprintf (header_file,
-	   "extern hash_table<rs6000_ovld_hasher> ovld_hash;\n\n");
+  fprintf (header_file, "extern ovlddata rs6000_instance_info[];\n");
+  fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n");
 
   fprintf (header_file, "extern void rs6000_autoinit_builtins ();\n\n");
+  fprintf (header_file,
+	   "extern bool rs6000_new_builtin_is_supported_p "
+	   "(rs6000_gen_builtins);\n");
+  fprintf (header_file,
+	   "extern tree rs6000_builtin_decl (unsigned, "
+	   "bool ATTRIBUTE_UNUSED);\n");
 }
 
 /* Callback functions used for generating trees for function types.  */
@@ -2466,18 +2470,38 @@ write_bif_static_init ()
   fprintf (init_file, "  };\n\n");
 }
 
-/* Write the decl and initializer for rs6000_overload_info[].  */
+/* Write the decls and initializers for rs6000_overload_info[] and
+   rs6000_instance_info[].  */
 static void
 write_ovld_static_init ()
 {
-  fprintf (init_file, "ovlddata rs6000_overload_info[RS6000_OVLD_MAX] =\n");
+  fprintf (init_file,
+	   "ovldrecord rs6000_overload_info[RS6000_OVLD_MAX "
+	   "- RS6000_OVLD_NONE] =\n");
   fprintf (init_file, "  {\n");
   fprintf (init_file, "    { /* RS6000_OVLD_NONE: */\n");
+  fprintf (init_file, "      \"\", NULL\n");
+  fprintf (init_file, "    },\n");
+  for (int i = 0; i <= curr_ovld_stanza; i++)
+    {
+      fprintf (init_file, "    { /* RS6000_OVLD_%s: */\n",
+	       ovld_stanzas[i].stanza_id);
+      fprintf (init_file, "      /* ovld_name */\t\"%s\",\n",
+	       ovld_stanzas[i].intern_name);
+      /* First-instance must currently be instantiated at run time.  */
+      fprintf (init_file, "      /* first_instance */\tNULL\n");
+      fprintf (init_file, "    },\n");
+    }
+  fprintf (init_file, "  };\n\n");
+
+  fprintf (init_file, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n");
+  fprintf (init_file, "  {\n");
+  fprintf (init_file, "    { /* RS6000_INST_NONE: */\n");
   fprintf (init_file, "      \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n");
   fprintf (init_file, "    },\n");
   for (int i = 0; i <= curr_ovld; i++)
     {
-      fprintf (init_file, "    { /* RS6000_OVLD_%s: */\n",
+      fprintf (init_file, "    { /* RS6000_INST_%s: */\n",
 	       ovlds[i].ovld_id_name);
       fprintf (init_file, "      /* bifname */\t\"%s\",\n",
 	       ovlds[i].proto.bifname);
@@ -2489,7 +2513,7 @@ write_ovld_static_init ()
       if (i < curr_ovld
 	  && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname))
 	fprintf (init_file,
-		 "&rs6000_overload_info[RS6000_OVLD_%s]\n",
+		 "&rs6000_instance_info[RS6000_INST_%s]\n",
 		 ovlds[i+1].ovld_id_name);
       else
 	fprintf (init_file, "NULL\n");
@@ -2508,20 +2532,6 @@ write_init_bif_table ()
 	       "  rs6000_builtin_info_x[RS6000_BIF_%s].fntype"
 	       "\n    = %s;\n",
 	       bifs[i].idname, bifs[i].fndecl);
-      fprintf (init_file,
-	       "  bifaddr = &rs6000_builtin_info_x[RS6000_BIF_%s];\n",
-	       bifs[i].idname);
-      fprintf (init_file,
-	       "  hash = rs6000_bif_hasher::hash (bifaddr);\n");
-      fprintf (init_file,
-	       "  slot = bif_hash.find_slot_with_hash (\n");
-      fprintf (init_file,
-	       "           \"%s\", hash, INSERT\n",
-	       bifs[i].proto.bifname);
-      fprintf (init_file,
-	       "         );\n");
-      fprintf (init_file,
-	       "  *slot = bifaddr;\n\n");
 
       fprintf (init_file,
 	       "  if (new_builtins_are_live)\n");
@@ -2573,49 +2583,46 @@ write_init_ovld_table ()
   for (int i = 0; i <= curr_ovld; i++)
     {
       fprintf (init_file,
-	       "  rs6000_overload_info[RS6000_OVLD_%s - base].fntype"
+	       "  rs6000_instance_info[RS6000_INST_%s].fntype"
 	       "\n    = %s;\n",
 	       ovlds[i].ovld_id_name, ovlds[i].fndecl);
 
       if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza)
 	{
+	  ovld_stanza *stanza = &ovld_stanzas[ovlds[i].stanza];
 	  fprintf (init_file, "\n");
+
+	  /* The fndecl for an overload is arbitrarily the first one
+	     for the overload.  We sort out the real types when
+	     processing the overload in the gcc front end.  */
 	  fprintf (init_file,
-		   "  ovldaddr = &rs6000_overload_info"
-		   "[RS6000_OVLD_%s - base];\n",
-		   ovlds[i].ovld_id_name);
+		   "  if (new_builtins_are_live)\n");
+	  fprintf (init_file, "    {\n");
 	  fprintf (init_file,
-		   "  hash = rs6000_ovld_hasher::hash (ovldaddr);\n");
+		   "      rs6000_builtin_decls_x[(int)RS6000_OVLD_%s] = t\n",
+		   stanza->stanza_id);
 	  fprintf (init_file,
-		   "  oslot = ovld_hash.find_slot_with_hash (\n");
+		   "        = add_builtin_function (\"%s\",\n",
+		   stanza->extern_name);
 	  fprintf (init_file,
-		   "            \"%s\", hash, INSERT\n",
-		   ovlds[i].proto.bifname);
+		   "                                %s,\n",
+		   ovlds[i].fndecl);
 	  fprintf (init_file,
-		   "         );\n");
+		   "                                (int)RS6000_OVLD_%s,"
+		   " BUILT_IN_MD,\n",
+		   stanza->stanza_id);
 	  fprintf (init_file,
-		   "  *oslot = ovldaddr;\n\n");
-	}
+		   "                                NULL, NULL_TREE);\n");
+	  fprintf (init_file, "    }\n\n");
 
-      fprintf (init_file,
-	       "  if (new_builtins_are_live)\n");
-      fprintf (init_file, "    {\n");
-      fprintf (init_file,
-	       "      rs6000_builtin_decls_x[(int)RS6000_OVLD_%s] = t\n",
-	       ovlds[i].ovld_id_name);
-      fprintf (init_file,
-	       "        = add_builtin_function (\"%s\",\n",
-	       ovlds[i].proto.bifname);
-      fprintf (init_file,
-	       "                                %s,\n",
-	       ovlds[i].fndecl);
-      fprintf (init_file,
-	       "                                (int)RS6000_OVLD_%s,"
-	       " BUILT_IN_MD,\n",
-	       ovlds[i].ovld_id_name);
-      fprintf (init_file,
-	       "                                NULL, NULL_TREE);\n");
-      fprintf (init_file, "    }\n\n");
+	  fprintf (init_file,
+		   "  rs6000_overload_info[RS6000_OVLD_%s - base]"
+		   ".first_instance\n",
+		   stanza->stanza_id);
+	  fprintf (init_file,
+		   "    = &rs6000_instance_info[RS6000_INST_%s];\n\n",
+		   ovlds[i].ovld_id_name);
+	}
     }
 }
 
@@ -2651,45 +2658,10 @@ write_init_file ()
   rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype);
   fprintf (init_file, "\n");
 
-  fprintf (init_file, "hashval_t\n");
-  fprintf (init_file, "rs6000_bif_hasher::hash (bifdata *bd)\n");
-  fprintf (init_file, "{\n");
-  fprintf (init_file, "  return htab_hash_string (bd->bifname);\n");
-  fprintf (init_file, "}\n\n");
-
-  fprintf (init_file, "bool\n");
-  fprintf (init_file,
-	   "rs6000_bif_hasher::equal (bifdata *bd, const char *name)\n");
-  fprintf (init_file, "{\n");
-  fprintf (init_file, "  return bd && name && !strcmp (bd->bifname, name);\n");
-  fprintf (init_file, "}\n\n");
-
-  fprintf (init_file, "hash_table<rs6000_bif_hasher> bif_hash (1024);\n\n");
-
-  fprintf (init_file, "hashval_t\n");
-  fprintf (init_file, "rs6000_ovld_hasher::hash (ovlddata *od)\n");
-  fprintf (init_file, "{\n");
-  fprintf (init_file, "  return htab_hash_string (od->bifname);\n");
-  fprintf (init_file, "}\n\n");
-
-  fprintf (init_file, "bool\n");
-  fprintf (init_file,
-	   "rs6000_ovld_hasher::equal (ovlddata *od, const char *name)\n");
-  fprintf (init_file, "{\n");
-  fprintf (init_file, "  return od && name && !strcmp (od->bifname, name);\n");
-  fprintf (init_file, "}\n\n");
-
-  fprintf (init_file, "hash_table<rs6000_ovld_hasher> ovld_hash (512);\n\n");
-
   fprintf (init_file, "void\n");
   fprintf (init_file, "rs6000_autoinit_builtins ()\n");
   fprintf (init_file, "{\n");
   fprintf (init_file, "  tree t;\n");
-  fprintf (init_file, "  bifdata **slot;\n");
-  fprintf (init_file, "  bifdata *bifaddr;\n");
-  fprintf (init_file, "  hashval_t hash;\n");
-  fprintf (init_file, "  ovlddata **oslot;\n");
-  fprintf (init_file, "  ovlddata *ovldaddr;\n\n");
   fprintf (init_file, "  timevar_start (TV_BILL);\n");
   rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype_init);
   fprintf (init_file, "\n");
diff --git a/gcc/config/rs6000/rs6000-overload.def b/gcc/config/rs6000/rs6000-overload.def
index 2104da7c3f5..21f83f51c8d 100644
--- a/gcc/config/rs6000/rs6000-overload.def
+++ b/gcc/config/rs6000/rs6000-overload.def
@@ -171,7 +171,8 @@
 ; vsi and vui arguments, but rather than building a define_expand
 ; for the instruction sequence generated for those, we do some RTL
 ; hackery.  Revisit whether we can remove that.  For now, keep this
-; much of the entry here to generate the #define, at least.
+; much of the entry here to generate the #define, at least.  Also
+; these entries are needed anyway by the rs6000-c.c logic.
 [VEC_ADDE, vec_adde, __builtin_vec_adde]
   vsq __builtin_vec_adde (vsq, vsq, vsq);
     VADDEUQM  VADDEUQM_VSQ
@@ -1017,20 +1018,10 @@
   vf __builtin_vec_expte (vf);
     VEXPTEFP
 
-[VEC_EXTRACTM, vec_extractm, __builtin_vec_vextractm, _ARCH_PWR10]
-  signed int __builtin_vec_vextractm (vuc);
-    VEXTRACTMB
-  signed int __builtin_vec_vextractm (vus);
-    VEXTRACTMH
-  signed int __builtin_vec_vextractm (vui);
-    VEXTRACTMW
-  signed int __builtin_vec_vextractm (vull);
-    VEXTRACTMD
-  signed int __builtin_vec_vextractm (vuq);
-    VEXTRACTMQ
-
-; There is no entry for vec_extract.  There is special handling for
-; this in altivec_resolve_overloaded_builtin in rs6000.c.
+; There are no actual builtins for vec_extract.  There is special handling for
+; this in altivec_resolve_overloaded_builtin in rs6000-c.c, where the call
+; is replaced by "pointer tricks."
+[VEC_EXTRACT, vec_extract, __builtin_vec_extract]
 
 [VEC_EXTRACT_FP_FROM_SHORTH, vec_extract_fp32_from_shorth, __builtin_vec_vextract_fp_from_shorth, _ARCH_PWR9]
   vf __builtin_vec_vextract_fp_from_shorth (vus);
@@ -1060,6 +1051,18 @@
   vull __builtin_vec_extractl (vull, vull, unsigned char);
     VEXTRACTDL
 
+[VEC_EXTRACTM, vec_extractm, __builtin_vec_vextractm, _ARCH_PWR10]
+  signed int __builtin_vec_vextractm (vuc);
+    VEXTRACTMB
+  signed int __builtin_vec_vextractm (vus);
+    VEXTRACTMH
+  signed int __builtin_vec_vextractm (vui);
+    VEXTRACTMW
+  signed int __builtin_vec_vextractm (vull);
+    VEXTRACTMD
+  signed int __builtin_vec_vextractm (vuq);
+    VEXTRACTMQ
+
 [VEC_EXTRACT4B, vec_extract4b, __builtin_vec_extract4b, _ARCH_PWR9]
   vull __builtin_vec_extract4b (vuc, const int);
     EXTRACT4B
@@ -1234,8 +1237,10 @@
   vull __builtin_vec_gnb (vuq, unsigned char);
     VGNB
 
-; There is no entry for vec_insert.  There is special handling for
-; this in altivec_resolve_overloaded_builtin in rs6000.c.
+; There are no actual builtins for vec_insert.  There is special handling for
+; this in altivec_resolve_overloaded_builtin in rs6000-c.c, where the call
+; is replaced by "pointer tricks."
+[VEC_INSERT, vec_insert, __builtin_vec_insert]
 
 [VEC_INSERTH, vec_inserth, __builtin_vec_inserth, _ARCH_PWR10]
   vuc __builtin_vec_inserth (unsigned char, vuc, unsigned int);
@@ -1833,9 +1838,17 @@
   void __builtin_vec_mtvscr (vui);
     MTVSCR  MTVSCR_VUI
 
-; Note that there is no entry for VEC_MUL.  See rs6000-c.c:
-; altivec_resolve_overloaded_builtin, where there is special-case
-; code for VEC_MUL.  TODO: Is this really necessary?  Investigate.
+; Note that the entries for VEC_MUL are currently ignored.  See rs6000-c.c:
+; altivec_resolve_overloaded_builtin, where there is special-case code for
+; VEC_MUL.  TODO: Is this really necessary?  Investigate.  Seven missing
+; prototypes here...no corresponding builtins.
+[VEC_MUL, vec_mul, __builtin_vec_mul]
+  vsll __builtin_vec_mul (vsll, vsll);
+    MUL_V2DI
+  vf __builtin_vec_mul (vf, vf);
+    XVMULSP
+  vd __builtin_vec_mul (vd, vd);
+    XVMULDP
 
 [VEC_MULE, vec_mule, __builtin_vec_mule]
   vss __builtin_vec_mule (vsc, vsc);
@@ -2205,8 +2218,10 @@
   vuq __builtin_vec_vparity_lsbb (vuq);
     VPRTYBQ  VPRTYBQ_U
 
-; There is no entry for vec_promote.  There is special handling for
-; this in altivec_resolve_overloaded_builtin in rs6000.c.
+; There are no actual builtins for vec_promote.  There is special handling for
+; this in altivec_resolve_overloaded_builtin in rs6000-c.c, where the call
+; is replaced by a constructor.
+[VEC_PROMOTE, vec_promote, __builtin_vec_promote]
 
 [VEC_RE, vec_re, __builtin_vec_re]
   vf __builtin_vec_re (vf);
@@ -2659,8 +2674,10 @@
   vf __builtin_vec_xxsplti32dx (vf, const int, float);
     VXXSPLTI32DX_V4SF
 
-; There is no entry for vec_splats.  There is special handling for
-; this in altivec_resolve_overloaded_builtin in rs6000.c.
+; There are no actual builtins for vec_splats.  There is special handling for
+; this in altivec_resolve_overloaded_builtin in rs6000-c.c, where the call
+; is replaced by a constructor.
+[VEC_SPLATS, vec_splats, __builtin_vec_splats]
 
 [VEC_SQRT, vec_sqrt, __builtin_vec_sqrt, __VSX__]
   vf __builtin_vec_sqrt (vf);
@@ -2888,6 +2905,10 @@
   void __builtin_vec_ste (vf, signed long long, float *);
     STVEWX  STVEWX_F
 
+; There are no builtins for VEC_STEP; this is handled directly
+; with a constant replacement in rs6000_resolve_overloaded_builtin.
+[VEC_STEP, vec_step, __builtin_vec_step]
+
 [VEC_STL, vec_stl, __builtin_vec_stl]
   void __builtin_vec_stl (vsc, signed long long, vsc *);
     STVXL_V16QI  STVXL_VSC
@@ -3428,13 +3449,13 @@
 
 [VEC_VSIE, scalar_insert_exp, __builtin_vec_scalar_insert_exp, _ARCH_PWR9]
   double __builtin_vec_scalar_insert_exp (unsigned int, unsigned int);
-    VSIEDP  VSIEDP_UI
+    VSIEDP
   double __builtin_vec_scalar_insert_exp (double, unsigned int);
-    VSIEDP  VSIEDP_D
+    VSIEDPF
   _Float128 __builtin_vec_scalar_insert_exp (unsigned long long, unsigned long long);
-    VSIEQP  VSIEQP_ULL
+    VSIEQP
   _Float128 __builtin_vec_scalar_insert_exp (_Float128, unsigned long long);
-    VSIEQP  VSIEQP_F128
+    VSIEQPF
 
 [VEC_VSTDC, scalar_test_data_class, __builtin_vec_scalar_test_data_class, _ARCH_PWR9]
   bool __builtin_vec_scalar_test_data_class (float, signed int);


More information about the Gcc-cvs mailing list