diff --git a/gcc/config/rs6000/rs6000-genbif.c b/gcc/config/rs6000/rs6000-genbif.c
index c84df1aa30f..ac640e14def 100644
--- a/gcc/config/rs6000/rs6000-genbif.c
+++ b/gcc/config/rs6000/rs6000-genbif.c
@@ -311,6 +311,52 @@ static rbt_strings bif_rbt;
 static rbt_strings ovld_rbt;
 static rbt_strings fntype_rbt;
 
+/* Mapping from type tokens to type node names.  */
+struct typemap
+{
+  const char *key;
+  const char *value;
+};
+
+/* This table must be kept in alphabetical order, as we use binary
+   search for table lookups in map_token_to_type_node.  */
+#define TYPE_MAP_SIZE 32
+static typemap type_map[TYPE_MAP_SIZE] =
+  {
+    { "df",	"double" },
+    { "di",	"intDI" },
+    { "hi",	"intHI" },
+    { "pv",	"ptr" },
+    { "qi",	"intQI" },
+    { "sf",	"float" },
+    { "si",	"intSI" },
+    { "tf",	"long_double" },
+    { "ti",	"intTI" },
+    { "udi",	"unsigned_intDI" },
+    { "uhi",	"unsigned_intHI" },
+    { "uqi",	"unsigned_intQI" },
+    { "usi",	"unsigned_intSI" },
+    { "uti",	"unsigned_intTI" },
+    { "uv16qi",	"unsigned_V16QI" },
+    { "uv1ti",	"unsigned_V1TI" },
+    { "uv2di",	"unsigned_V2DI" },
+    { "uv4si",	"unsigned_V4SI" },
+    { "uv8hi",	"unsigned_V8HI" },
+    { "v",	"void" },
+    { "v16qi",	"V16QI" },
+    { "v1ti",	"V1TI" },
+    { "v2df",	"V2DF" },
+    { "v2di",	"V2DI" },
+    { "v4sf",	"V4SF" },
+    { "v4si",	"V4SI" },
+    { "v8hi",	"V8HI" },
+    { "vb16qi",	"bool_V16QI" },
+    { "vb2di",	"bool_V2DI" },
+    { "vb4si",	"bool_V4SI" },
+    { "vb8hi",	"bool_V8HI" },
+    { "vp8hi",	"pixel_V8HI" },
+  };
+
 /* Pointer to a diagnostic function.  */
 void (*diag) (const char *, ...) __attribute__ ((format (printf, 1, 2)))
   = NULL;
@@ -1761,6 +1807,80 @@ write_extern_fntype (char *str)
   fprintf (header_file, "extern tree %s;\n", str);
 }
 
+void
+write_fntype (char *str)
+{
+  fprintf (init_file, "tree %s;\n", str);
+}
+
+/* Look up TOK in the type map and return the corresponding string used
+   to build the type node.  */
+static const char *
+map_token_to_type_node (char *tok)
+{
+  int low = 0;
+  int high = TYPE_MAP_SIZE - 1;
+  int mid = (low + high) >> 1;
+  int cmp;
+
+  while ((cmp = strcmp (type_map[mid].key, tok)) && low < high)
+    {
+      if (cmp < 0)
+	low = (low == mid ? mid + 1 : mid);
+      else
+	high = (high == mid ? mid - 1: mid);
+      mid = (low + high) >> 1;
+    }
+
+  if (low > high)
+    {
+      (*diag) ("token '%s' doesn't appear in the type map!\n", tok);
+      exit (EC_INTERR);
+    }
+
+  return type_map[mid].value;
+}
+
+/* Write the type node corresponding to TOK.  */
+static void
+write_type_node (char *tok)
+{
+  const char *str = map_token_to_type_node (tok);
+  fprintf (init_file, "%s_type_node", str);
+}
+
+/* Write an initializer for a function type identified by STR.  */
+void
+write_fntype_init (char *str)
+{
+  char *tok;
+
+  /* Avoid side effects of strtok on the original string by using a copy.  */
+  char *buf = (char *) malloc (strlen (str) + 1);
+  strcpy (buf, str);
+
+  fprintf (init_file, "  %s\n    = build_function_type_list (", buf);
+  tok = strtok (buf, "_");
+  write_type_node (tok);
+  tok = strtok (0, "_");
+  assert (tok);
+  assert (!strcmp (tok, "ftype"));
+
+  tok = strtok (0, "_");
+  if (tok)
+    fprintf (init_file, ",\n\t\t\t\t");
+
+  /* Note:  A function with no arguments ends with '_ftype_v'.  */
+  while (tok && strcmp (tok, "v"))
+    {
+      write_type_node (tok);
+      tok = strtok (0, "_");
+      fprintf (init_file, ",\n\t\t\t\t");
+    }
+  fprintf (init_file, "NULL_TREE);\n");
+  free (buf);
+}
+
 /* Write everything to the header file (rs6000-bif.h).  */
 static int
 write_header_file ()
@@ -1784,10 +1904,257 @@ write_header_file ()
   return 1;
 }
 
+/* Write code to initialize the built-in function table.  */
+static void
+write_init_bif_table ()
+{
+  int last_stanza = -1;
+
+  for (int i = 0; i <= curr_bif; i++)
+    {
+      if (last_stanza != bifs[i].stanza)
+	{
+	  if (last_stanza != -1)
+	    fprintf (init_file, "    }\n");
+	  fprintf (init_file, "  if (%s)\n    {\n",
+		   bif_stanzas[bifs[i].stanza]);
+	  last_stanza = bifs[i].stanza;
+	}
+      fprintf (init_file,
+	       "      rs6000_builtin_info_x[RS6000_BIF_%s].bifname"
+	       "\n        = \"%s\";\n",
+	       bifs[i].idname, bifs[i].proto.bifname);
+      fprintf (init_file,
+	       "      rs6000_builtin_info_x[RS6000_BIF_%s].fntype"
+	       "\n        = %s;\n",
+	       bifs[i].idname, bifs[i].fndecl);
+      fprintf (init_file,
+	       "      rs6000_builtin_info_x[RS6000_BIF_%s].icode"
+	       "\n        = CODE_FOR_%s;\n",
+	       bifs[i].idname, bifs[i].patname);
+      fprintf (init_file,
+	       "      rs6000_builtin_info_x[RS6000_BIF_%s].bifattrs"
+	       "\n        = 0",
+	       bifs[i].idname);
+      if (bifs[i].kind == FNK_CONST)
+	fprintf (init_file, " | bif_const_bit");
+      else if (bifs[i].kind == FNK_PURE)
+	fprintf (init_file, " | bif_pure_bit");
+      else if (bifs[i].kind == FNK_MATH)
+	fprintf (init_file, " | bif_round_bit");
+      if (bifs[i].attrs.isinit)
+	fprintf (init_file, " | bif_init_bit");
+      if (bifs[i].attrs.isset)
+	fprintf (init_file, " | bif_set_bit");
+      if (bifs[i].attrs.isext)
+	fprintf (init_file, " | bif_ext_bit");
+      if (bifs[i].attrs.isnosoft)
+	fprintf (init_file, " | bif_nosoft_bit");
+      if (bifs[i].attrs.isldv)
+	fprintf (init_file, " | bif_ldv_bit");
+      if (bifs[i].attrs.isstv)
+	fprintf (init_file, " | bif_stv_bit");
+      if (bifs[i].attrs.isreve)
+	fprintf (init_file, " | bif_reve_bit");
+      if (bifs[i].attrs.isabs)
+	fprintf (init_file, " | bif_abs_bit");
+      if (bifs[i].attrs.ispred)
+	fprintf (init_file, " | bif_pred_bit");
+      if (bifs[i].attrs.ishtm)
+	fprintf (init_file, " | bif_htm_bit");
+      fprintf (init_file, ";\n");
+      fprintf (init_file,
+	       "      rs6000_builtin_info_x[RS6000_BIF_%s].restr_opnd"
+	       "\n        = %d;\n",
+	       bifs[i].idname, bifs[i].proto.restr_opnd);
+      if (bifs[i].proto.restr_opnd)
+	{
+	  const char *res
+	    = (bifs[i].proto.restr == RES_BITS ? "RES_BITS"
+	       : (bifs[i].proto.restr == RES_RANGE ? "RES_RANGE"
+		  : (bifs[i].proto.restr == RES_VALUES ? "RES_VALUES"
+		     : "ERROR")));
+	  fprintf (init_file,
+		   "      rs6000_builtin_info_x[RS6000_BIF_%s].restr"
+		   "\n        = %s;\n",
+		   bifs[i].idname, res);
+	  fprintf (init_file,
+		   "      rs6000_builtin_info_x[RS6000_BIF_%s].restr_val1"
+		   "\n        = %d;\n",
+		   bifs[i].idname, bifs[i].proto.restr_val1);
+	  fprintf (init_file,
+		   "      rs6000_builtin_info_x[RS6000_BIF_%s].restr_val2"
+		   "\n        = %d;\n",
+		   bifs[i].idname, bifs[i].proto.restr_val2);
+	}
+      fprintf (init_file, "\n");
+
+      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,
+	       "#ifdef NEW_BUILTINS_ARE_LIVE\n");
+      fprintf (init_file,
+	       "      rs6000_builtin_decls[(int)RS6000_BIF_%s]\n",
+	       bifs[i].idname);
+      fprintf (init_file,
+	       "        = add_builtin_function (\"%s\",\n",
+	       bifs[i].proto.bifname);
+      fprintf (init_file,
+	       "                                %s,\n",
+	       bifs[i].fndecl);
+      fprintf (init_file,
+	       "                                (int)RS6000_BIF_%s, NULL,"
+	       " NULL_TREE);\n",
+	       bifs[i].idname);
+      fprintf (init_file,
+	       "#endif\n");
+
+      if (i < curr_bif)
+	fprintf (init_file, "\n");
+    }
+  fprintf (init_file, "    }\n\n");
+}
+
+/* Write code to initialize the overload table.  */
+static void
+write_init_ovld_table ()
+{
+  fprintf (init_file, "  int base = RS6000_BIF_MAX;\n\n");
+
+  for (int i = 0; i <= curr_ovld; i++)
+    {
+      fprintf (init_file,
+	       "  rs6000_overload_info[RS6000_OVLD_%s - base].bifname"
+	       "\n    = \"%s\";\n",
+	       ovlds[i].idname, ovlds[i].proto.bifname);
+      fprintf (init_file,
+	       "  rs6000_overload_info[RS6000_OVLD_%s - base].bifid"
+	       "\n    = RS6000_BIF_%s;\n",
+	       ovlds[i].idname, ovlds[i].idname);
+      fprintf (init_file,
+	       "  rs6000_overload_info[RS6000_OVLD_%s - base].fntype"
+	       "\n    = %s;\n",
+	       ovlds[i].idname, ovlds[i].fndecl);
+      fprintf (init_file,
+	       "  rs6000_overload_info[RS6000_OVLD_%s - base].next"
+	       "\n    = ", ovlds[i].idname);
+      if (i < curr_ovld
+	  && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname))
+	fprintf (init_file,
+		 "&rs6000_overload_info[RS6000_OVLD_%s - base];\n",
+		 ovlds[i+1].idname);
+      else
+	fprintf (init_file, "NULL;\n");
+
+      if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza)
+	{
+	  fprintf (init_file, "\n");
+
+	  fprintf (init_file,
+		   "  ovldaddr = &rs6000_overload_info"
+		   "[RS6000_OVLD_%s - base];\n",
+		   ovlds[i].idname);
+	  fprintf (init_file,
+		   "  hash = rs6000_ovld_hasher::hash (ovldaddr);\n");
+	  fprintf (init_file,
+		   "  oslot = ovld_hash.find_slot_with_hash (\n");
+	  fprintf (init_file,
+		   "            \"%s\", hash, INSERT\n",
+		   ovlds[i].proto.bifname);
+	  fprintf (init_file,
+		   "         );\n");
+	  fprintf (init_file,
+		   "  *oslot = ovldaddr;\n");
+	}
+
+      if (i < curr_ovld)
+	fprintf (init_file, "\n");
+    }
+}
+
 /* Write everything to the initialization file (rs6000-bif.c).  */
 static int
 write_init_file ()
 {
+  write_autogenerated_header (init_file);
+
+  fprintf (init_file, "#include \"config.h\"\n");
+  fprintf (init_file, "#include \"system.h\"\n");
+  fprintf (init_file, "#include \"coretypes.h\"\n");
+  fprintf (init_file, "#include \"backend.h\"\n");
+  fprintf (init_file, "#include \"rtl.h\"\n");
+  fprintf (init_file, "#include \"tree.h\"\n");
+  fprintf (init_file, "#include \"insn-codes.h\"\n");
+  fprintf (init_file, "#include \"rs6000-bif.h\"\n");
+  fprintf (init_file, "\n");
+
+  fprintf (init_file,
+	   "bifdata rs6000_builtin_info_x[RS6000_BIF_MAX];\n\n");
+  fprintf (init_file,
+	   "ovlddata rs6000_overload_info[RS6000_OVLD_MAX"
+	   " - RS6000_BIF_MAX];\n\n");
+
+  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, "  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");
+  rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype_init);
+  fprintf (init_file, "\n");
+
+  write_init_bif_table ();
+  write_init_ovld_table ();
+
+  fprintf (init_file, "}\n");
   return 1;
 }
 
