diff mbox

[RFC] Builtin infrastructure change

Message ID 20111001000142.GA5759@hungry-tiger.westford.ibm.com
State New
Headers show

Commit Message

Michael Meissner Oct. 1, 2011, 12:01 a.m. UTC
On Mon, Sep 26, 2011 at 04:40:01PM +0200, Richard Guenther wrote:
> On Wed, Sep 14, 2011 at 10:38 PM, Richard Henderson <rth@redhat.com> wrote:
> > On 09/13/2011 04:27 PM, Michael Meissner wrote:
> >> This patch touches a bunch of files, but most of the changes are fairly
> >> mechanical.  What this does is change the infrastructure of how machine
> >> independent builtin functions are handled.  At this point, there is no change
> >> to the compiler from a user perspective.  Instead of having two parallel arrays
> >> that have tree pointers for built-in functions:
> >>
> >>       built_in_decls
> >>       implicit_built_in_decls
> >>
> >> I have replaced these by two macros that call inline functions:
> >>
> >>       BUILT_IN_DECLS
> >>       IMPLICIT_BUILT_IN_DECLS
> >>
> >> and changed the other parts that want to modify the builtins.  By changing it
> >> to a functional approach instead of an array, we can more easily change the
> >> code underneath.
> > 
> > Why bother with the case change and poisoning?  Merely changing the type of
> > the symbol from object to function ought to be sufficient to catch all
> > users at compile time.
> >
> > I say this because I'm not keen on functions using all-caps names...
> 
> Yeah, I agree.
> 
> Richard.

I've reworked the patch to just change the arrays into functions, and it did
catch Jakub's on the 27th that touched the arrays when I merged up my tree to
subversion id 179369 yesterday.

Now, the reason why I was doing the abstraction was to answer some long
standing gripes that all of the builtin functions must be created when the
compiler starts up, and that takes extra space and memory.  At the moment, we
have 739 standard builtins, 1,002 builtins in the x86 port, and 954 builtins in
the PowerPC.  I am in the process of doing the next step that allocates all of
the standard builtins n a lazy fashion, and I'm wondering whether it will make
enough of a different to worry about.  With my current sources, I save about
716 kilobytes by not building the standard builtin declarations on a dummy
program.  I would expect then that the x86 might save 1.6 megabytes, and the
powerpc 1.5 megabytes.  At the moment, I am not building the function and
attributes on demand, so we might see a little more savings from that,
particularly with all of the machine builtins with all sorts of types.

Is this enough of a savings to continue on?  I'm of two minds about it, one is
that a savings is a savings, and it would help a little bit for overloaded
systems, and on the other hand, once you get to compiling larger programs, I'm
not sure you would notice.  If people don't think it is worthwhile, I can stop
work on lazy builtins.  I would like to submit the infrastructure change in any
case (unless the global reviewer and release managers are against it).

The way my new stuff works, is instead of creating the decl, it just marks the
identifier node, remembering the builtin function index in the identifier node
itself (using a combination of the RID keyword byte and the address_space byte
that is in every identifier).  Then when the lexer sees the identifier, it
calls the langhook to actually create the builtin and link it in.  Right now, I
need to track down to make sure this new declaration does not trigger the
implicit redeclaration warning, and add similar support to C++.

Here are the patches for just the infrastructure change that should be similar
to my previous patches.  Are there any other comments on these patches.

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

	* tree.h (built_in_decls): Change builtin interface from being an
	array to an inline function for both normal and implicit builtin
	functions.  Change all read references to built_in_decls and
	implicit_built_in_decls arrays to functions, and change write
	references to call built_in_set_decl and built_in_set_implicit.
	(implicit_built_in_decls): Ditto.
	(struct built_in_decl_info): Ditto.
	(built_in_info): Ditto.
	(built_in_get_decl): Ditto.
	(built_in_set_decl): Ditto.
	(built_in_set_decl_add): Ditto.
	(built_in_set_implicit): Ditto.
	* tree.c (iterative_hash_expr): Ditto.
	(local_define_builtin): Ditto.
	(build_common_builtin_nodes): Ditto.
	* tree-complex.c (expand_complex_libcall): Ditto.
	* tree-loop-distribution.c (generate_memset_zero): Ditto.
	* builtins.c (built_in_info): Ditto.
	(built_in_decls): Ditto.
	(implicit_built_in_decls): Ditto.
	(mathfn_built_in_1): Ditto.
	(expand_builtin_cexpi): Ditto.
	(expand_builtin_mempcpy_args): Ditto.
	(expand_builtin_stpcpy): Ditto.
	(gimplify_va_arg_expr): Ditto.
	(expand_builtin_sync_operation): Ditto.
	(build_builtin_expect_predicate): Ditto.
	(fold_builtin_memory_op): Ditto.
	(fold_builtin_strcpy): Ditto.
	(fold_builtin_strncpy): Ditto.
	(fold_builtin_interclass_mathfn): Ditto.
	(fold_builtin_classify): Ditto.
	(fold_builtin_2): Ditto.
	(fold_builtin_strstr): Ditto.
	(fold_builtin_strpbrk): Ditto.
	(fold_builtin_strcat): Ditto.
	(fold_builtin_strncat): Ditto.
	(fold_builtin_strcspn): Ditto.
	(fold_builtin_fputs): Ditto.
	(fold_builtin_sprintf): Ditto.
	(fold_builtin_snprintf): Ditto.
	(expand_builtin_memory_chk): Ditto.
	(fold_builtin_stxcpy_chk): Ditto.
	(fold_builtin_strncpy_chk): Ditto.
	(fold_builtin_strcat_chk): Ditto.
	(fold_builtin_strncat_chk): Ditto.
	(fold_builtin_sprintf_chk_1): Ditto.
	(fold_builtin_printf): Ditto.
	(fold_builtin_fprintf): Ditto.
	(fold_call_stmt): Ditto.
	(set_builtin_user_assembler_name): Ditto.
	* tree-emults.c (emutls_common_1): Ditto.
	(lower_emutls_function_body): Ditto.
	* omp-low.c (scan_omp): Ditto.
	(lower_rec_input_clauses): Ditto.
	(lower_reduction_clauses): Ditto.
	(expand_parallel_call): Ditto.
	(expand_task_call): Ditto.
	(maybe_catch_exception): Ditto.
	(optimize_omp_library_calls): Ditto.
	(expand_omp_for_generic): Ditto.
	(expand_omp_for_static_chunk): Ditto.
	(expand_omp_sections): Ditto.
	(expand_omp_atomic_pipeline): Ditto.
	(expand_omp_atomic_mutex): Ditto.
	(lower_omp_single_simple): Ditto.
	(lower_omp_single_copy): Ditto.
	(lower_omp_single): Ditto.
	(lower_omp_master): Ditto.
	(lower_omp_ordered): Ditto.
	(lower_omp_critical): Ditto.
	* tree-ssa-ccp.c (optimize_stdarg_builtin): Ditto.
	* tree-ssa-math-opts.c (execute_optimize_bswap): Ditto.
	* tree-ssa-strlen.c (get_string_length): Ditto.
	* gimple-low.c (lower_function_body): Ditto.
	(lower_builtin_setjmp): Ditto.
	* c-decl.c (finish_decl): Ditto.
	(merge_decls): Ditto.
	* tree-eh.c (lower_resx): ditto.
	(lower_eh_dispatch): Ditto.
	* function.c (gimplify_parameters): Ditto.
	* c-typeck.c (build_function_call_vec): Ditto.
	* gimplify.c (build_stack_save_restore): Ditto.
	(gimplify_vla_decl): Ditto.
	(gimplify_modify_expr_to_memcpy): Ditto.
	(gimplify_modify_expr_to_memset): Ditto.
	(gimplify_variable_sized_compare): Ditto.
	(gimplify_function_tree): Ditto.
	* calls.c (emit_call_1): Ditto.
	* tree-nested.c (convert_nl_goto_reference): Ditto.
	(convert_tramp_reference_op): Ditto.
	(finalize_nesting_tree_1): Ditto.
	* tree-ssa-loop-prefetch.c (issue_prefetch_ref): Ditto.
	(tree_ssa_prefetch_arrays): Ditto.
	* tree-streamer-in.c (streamer_get_builtin_tree): Ditto.
	* langhooks.c (add_builtin_function_common): Ditto.
	(add_builtin_function_nobind): Ditto.
	(add_builtin_function): Ditto.
	(add_builtin_function_ext_scope): Ditto.
	* langhooks.h (add_builtin_function_nobind): Ditto.
	* config/sparc/sparc.c (sparc_gimplify_va_arg): Ditto.
	* config/i386/i386.c (ix86_gimplify_va_arg): Ditto.
	(ix86_veclibabi_svml): Ditto.
	(ix86_veclibabi_acml): Ditto.
	* config/vms/vms.c (vms_patch_builtins): Ditto.
	* config/ia64/ia64.c (ia64_init_builtins): Ditto.
	* config/rs6000/rs6000.c (rs6000_builtin_vectorized_libmass): Ditto.
	(rs6000_gimplify_va_arg): Ditto.
	(rs6000_init_builtins): Ditto.
	* config/darwin.c (darwin_override_options): Ditto.
	(darwin_patch_builtin): Ditto.
	(darwin_rename_builtins): Ditto.
	* config/pa/pa.c (pa_init_builtins): Ditto.

	* builtins.def (BUILT_IN_NONE): Make sure 0 is not a legitimate
	builtin function index.

	* config/rs6000/rs6000.c (rs6000_debug_reg_global): Print size of
	the function decl node if -mdebug=reg.

[gcc/ada]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc-interface/utils.c (def_builtin_1): Change builtin interface
	from being an array to an inline function for both normal and
	implicit builtin functions.  Change all read references to
	built_in_decls and implicit_built_in_decls arrays to functions,
	and change write references to call built_in_set_decl,
	built_in_set_decl_add or built_in_set_implicit.
	* gcc-interface/trans.c (Exception_Handler_to_gnu_zcx): Ditto.
	(gnat_to_gnu): Ditto.

[gcc/c-family]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* c-common.c (def_builtin_1): Change builtin interface from being
	an array to an inline function for both normal and implicit
	builtin functions.  Change all read references to built_in_decls
	and implicit_built_in_decls arrays to functions, and change write
	references to call built_in_set_decl, built_in_set_decl_add, or
	built_in_set_implicit.
	(resolve_overloaded_builtin): Ditto.
	* c-omp.c (c_finish_omp_barrier): Ditto.
	(c_finish_omp_taskwait): Ditto.
	(c_finish_omp_taskyield): Ditto.
	(c_finish_omp_flush): Ditto.

[gcc/cp]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* decl.c (duplicate_decls): Change builtin interface from being an
	array to an inline function for both normal and implicit builtin
	functions.  Change all read references to built_in_decls and
	implicit_built_in_decls arrays to functions, and change write
	references to call built_in_set_decl, built_in_set_decl_add, or
	built_in_set_implicit.
	* except.c (build_eh_type_type): Ditto.
	* semantics.c (finish_omp_atomic): Ditto.
	(finish_omp_barrier): Ditto.
	(finish_omp_flush): Ditto.
	(finish_omp_taskwait): Ditto.

[gcc/fortran]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* trans.c (gfc_call_malloc): Change builtin interface from being
	an array to an inline function for both normal and implicit
	builtin functions.  Change all read references to built_in_decls
	and implicit_built_in_decls arrays to functions, and change write
	references to call built_in_set_decl, built_in_set_decl_add, or
	built_in_set_implicit.
	(gfc_allocate_using_malloc): Ditto.
	(gfc_call_free): Ditto.
	(gfc_deallocate_with_status): Ditto.
	(gfc_deallocate_scalar_with_status): Ditto.
	(gfc_call_realloc): Ditto.
	(gfc_unlikely): Ditto.
	(gfc_likely): Ditto.
	* f95-lang.c (gfc_define_builtin): Ditto.
	(gfc_init_builtin_functions): Ditto.
	* trans-decl.c (create_main_function): Ditto.
	* trans-intrinsic.c (builtin_decl_for_precision): Ditto.
	(gfc_build_intrinsic_lib_fndecls): Ditto.
	(gfc_conv_intrinsic_minmax): Ditto.
	(gfc_conv_intrinsic_leadz): Ditto.
	(gfc_conv_intrinsic_trailz): Ditto.
	(gfc_conv_intrinsic_popcnt_poppar): Ditto.
	(gfc_conv_intrinsic_isnan): Ditto.
	(gfc_conv_intrinsic_transfer): Ditto.
	(scalar_transfer): Ditto.
	(gfc_conv_intrinsic_repeat): Ditto.

[gcc/go]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gofrontend/gogo-tree.cc (make_trampoline): Change builtin
	interface from being an array to an inline function for both
	normal and implicit builtin functions.  Change all read references
	to built_in_decls and implicit_built_in_decls arrays to functions,
	and change write references to call built_in_set_decl,
	built_in_set_decl_add, or built_in_set_implicit.

[gcc/java]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* class.c (build_static_field_ref): Change builtin interface from
	being an array to an inline function for both normal and implicit
	builtin functions.  Change all read references to built_in_decls
	and implicit_built_in_decls arrays to functions, and change write
	references to call built_in_set_decl, built_in_set_decl_add, or
	built_in_set_implicit.
	* decl.c (java_init_decl_processing): Ditto.
	* except.c (expand_end_java_handler): Ditto.
	* builtins.c (compareAndSwapInt_builtin): Ditto.
	(compareAndSwapLong_builtin): Ditto.
	(compareAndSwapObject_builtin): Ditto.
	(compareAndSwapObject_builtin): Ditto.
	(putVolatile_builtin): Ditto.
	(getVolatile_builtin): Ditto.
	(define_builtin): Ditto.
	(check_for_builtin): Ditto.
	* expr.c (rewrite_arglist_getcaller): Ditto.
	(expand_java_field_op): Ditto.

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

	* lto-lang.c (def_builtin_1): Change builtin interface from being
	an array to an inline function for both normal and implicit
	builtin functions.  Change all read references to built_in_decls
	and implicit_built_in_decls arrays to functions, and change write
	references to call built_in_set_decl, built_in_set_decl_add, or
	built_in_set_implicit.

[gcc/objc]
2011-09-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* objc-next-runtime-abi-01.c (objc_build_exc_ptr): Change builtin
	interface from being an array to an inline function for both
	normal and implicit builtin functions.  Change all read references
	to built_in_decls and implicit_built_in_decls arrays to functions,
	and change write references to call built_in_set_decl,
	built_in_set_decl_add, or built_in_set_implicit.
	* objc-next-runtime-abi-02.c (objc_build_exc_ptr): Ditto.
	* objc-gnu-runtime-abi-01.c (objc_build_exc_ptr): Ditto.

Comments

Joseph Myers Oct. 1, 2011, 2:11 p.m. UTC | #1
On Fri, 30 Sep 2011, Michael Meissner wrote:

> Is this enough of a savings to continue on?  I'm of two minds about it, one is

The thing to measure is not so much memory as startup time (how long it 
takes to compile an empty source file), which is important for libraries 
and programs using a coding style with lots of small source files.
Michael Meissner Oct. 4, 2011, 12:07 a.m. UTC | #2
On Sat, Oct 01, 2011 at 02:11:27PM +0000, Joseph S. Myers wrote:
> On Fri, 30 Sep 2011, Michael Meissner wrote:
> 
> > Is this enough of a savings to continue on?  I'm of two minds about it, one is
> 
> The thing to measure is not so much memory as startup time (how long it 
> takes to compile an empty source file), which is important for libraries 
> and programs using a coding style with lots of small source files.

With my current changes which has modified the standard builtins to be lazy,
but I haven't yet done the machine dependent builtins, I saw a difference of
0.0022 seconds (0.0170 vs. 0.0148) on my 3 year old Intel core 2 laptop.  I did
14 runs in total, and skipped the fastest 2 runs and slowest 2 runs, and then
averaged the 10 runs in the middle.  I built boostrap builds with release
checking with the top of subversion head without changes and with my changes.

So at this point, I'm wondering whether it is worth it to finish the
optimization for lazy builtins.
Richard Biener Oct. 4, 2011, 12:44 p.m. UTC | #3
On Tue, Oct 4, 2011 at 2:07 AM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> On Sat, Oct 01, 2011 at 02:11:27PM +0000, Joseph S. Myers wrote:
>> On Fri, 30 Sep 2011, Michael Meissner wrote:
>>
>> > Is this enough of a savings to continue on?  I'm of two minds about it, one is
>>
>> The thing to measure is not so much memory as startup time (how long it
>> takes to compile an empty source file), which is important for libraries
>> and programs using a coding style with lots of small source files.
>
> With my current changes which has modified the standard builtins to be lazy,
> but I haven't yet done the machine dependent builtins, I saw a difference of
> 0.0022 seconds (0.0170 vs. 0.0148) on my 3 year old Intel core 2 laptop.  I did
> 14 runs in total, and skipped the fastest 2 runs and slowest 2 runs, and then
> averaged the 10 runs in the middle.  I built boostrap builds with release
> checking with the top of subversion head without changes and with my changes.
>
> So at this point, I'm wondering whether it is worth it to finish the
> optimization for lazy builtins.

I think it is.

+/* Return the tree node for a builtin function or NULL, indexing into the
+   array.  */
+static inline tree
+built_in_set_decl_add (enum built_in_function fncode, int addend)
+{
+  return built_in_decls ((enum built_in_function)(((int)fncode) + addend));
+}

this doesn't seem to "set" anything.  Mistake?

+static inline tree
+built_in_decls (enum built_in_function fncode)

I'd prefer singular, built_in_decl () instead of plural.

+static inline tree
+implicit_built_in_decls (enum built_in_function fncode)

Likewise.

+/* Initialize an implicit builtin function.  */
+static inline void
+built_in_set_implicit (enum built_in_function fncode, tree implicit)

and built_in_set_implicit_decl (or rather set_implicit_built_in_decl - hm,
I guess I'm now bikeshedding ;)).

The patch is ok with the built_in_set_decl_add mystery resolved
(I'd best not have the function at all but perform the ugly add and casting
in the few callers -- it _is_ ugly to do that after all, so it might as well
look so ;)).

It would be nice to use singular/plural consistently (different currently
for set and get, I prefer singular).  The rest of the bikeshedding - oh well ;)

Thanks,
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
>
Michael Meissner Oct. 4, 2011, 2:06 p.m. UTC | #4
On Tue, Oct 04, 2011 at 02:44:00PM +0200, Richard Guenther wrote:
> On Tue, Oct 4, 2011 at 2:07 AM, Michael Meissner
> <meissner@linux.vnet.ibm.com> wrote:
> > On Sat, Oct 01, 2011 at 02:11:27PM +0000, Joseph S. Myers wrote:
> >> On Fri, 30 Sep 2011, Michael Meissner wrote:
> >>
> >> > Is this enough of a savings to continue on?  I'm of two minds about it, one is
> >>
> >> The thing to measure is not so much memory as startup time (how long it
> >> takes to compile an empty source file), which is important for libraries
> >> and programs using a coding style with lots of small source files.
> >
> > With my current changes which has modified the standard builtins to be lazy,
> > but I haven't yet done the machine dependent builtins, I saw a difference of
> > 0.0022 seconds (0.0170 vs. 0.0148) on my 3 year old Intel core 2 laptop.  I did
> > 14 runs in total, and skipped the fastest 2 runs and slowest 2 runs, and then
> > averaged the 10 runs in the middle.  I built boostrap builds with release
> > checking with the top of subversion head without changes and with my changes.
> >
> > So at this point, I'm wondering whether it is worth it to finish the
> > optimization for lazy builtins.
> 
> I think it is.
> 
> +/* Return the tree node for a builtin function or NULL, indexing into the
> +   array.  */
> +static inline tree
> +built_in_set_decl_add (enum built_in_function fncode, int addend)
> +{
> +  return built_in_decls ((enum built_in_function)(((int)fncode) + addend));
> +}
> 
> this doesn't seem to "set" anything.  Mistake?

Yes, it was a mistake (though once the lazy builtins are done, it may do a set
to create the function decl the first time the builtin is touched).

> +static inline tree
> +built_in_decls (enum built_in_function fncode)
> 
> I'd prefer singular, built_in_decl () instead of plural.

Ok.  I was just using the array name, but singular is better.

> +static inline tree
> +implicit_built_in_decls (enum built_in_function fncode)
> 
> Likewise.

Ok, if I'm going to change the name anyway, I think I will make it
built_in_decl_implicit instead.

> +/* Initialize an implicit builtin function.  */
> +static inline void
> +built_in_set_implicit (enum built_in_function fncode, tree implicit)
> 
> and built_in_set_implicit_decl (or rather set_implicit_built_in_decl - hm,
> I guess I'm now bikeshedding ;)).

> The patch is ok with the built_in_set_decl_add mystery resolved
> (I'd best not have the function at all but perform the ugly add and casting
> in the few callers -- it _is_ ugly to do that after all, so it might as well
> look so ;)).

Originally I had kept the math inline, but some of the OMP functions were
running into the 80 character line limit, particularly with the need to make
sure everything correctly cast to int or enum for C++.

> It would be nice to use singular/plural consistently (different currently
> for set and get, I prefer singular).  The rest of the bikeshedding - oh well ;)

And whether it is builtin or built_in, since the compiler is inconsistant.
Joseph Myers Oct. 4, 2011, 3:36 p.m. UTC | #5
On Mon, 3 Oct 2011, Michael Meissner wrote:

> On Sat, Oct 01, 2011 at 02:11:27PM +0000, Joseph S. Myers wrote:
> > On Fri, 30 Sep 2011, Michael Meissner wrote:
> > 
> > > Is this enough of a savings to continue on?  I'm of two minds about it, one is
> > 
> > The thing to measure is not so much memory as startup time (how long it 
> > takes to compile an empty source file), which is important for libraries 
> > and programs using a coding style with lots of small source files.
> 
> With my current changes which has modified the standard builtins to be lazy,
> but I haven't yet done the machine dependent builtins, I saw a difference of
> 0.0022 seconds (0.0170 vs. 0.0148) on my 3 year old Intel core 2 laptop.  I did
> 14 runs in total, and skipped the fastest 2 runs and slowest 2 runs, and then
> averaged the 10 runs in the middle.  I built boostrap builds with release
> checking with the top of subversion head without changes and with my changes.
> 
> So at this point, I'm wondering whether it is worth it to finish the
> optimization for lazy builtins.

That's a 13% improvement.  It's very definitely worthwhile - most compile 
time improvements are probably 1% or less.
diff mbox

Patch

Index: gcc/tree-complex.c
===================================================================
--- gcc/tree-complex.c	(.../trunk)	(revision 179369)
+++ gcc/tree-complex.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -956,7 +956,7 @@  expand_complex_libcall (gimple_stmt_iter
 	     (BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
   else
     gcc_unreachable ();
-  fn = built_in_decls[bcode];
+  fn = built_in_decls (bcode);
 
   stmt = gimple_build_call (fn, 4, ar, ai, br, bi);
   gimple_call_set_lhs (stmt, lhs);
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(.../trunk)	(revision 179369)
+++ gcc/c-family/c-common.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -5173,9 +5173,9 @@  def_builtin_1 (enum built_in_function fn
     add_builtin_function (libname, libtype, fncode, fnclass,
 			  NULL, fnattrs);
 
-  built_in_decls[(int) fncode] = decl;
+  built_in_set_decl (fncode, decl);
   if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
+    built_in_set_implicit (fncode, decl);
 }
 
 /* Nonzero if the type T promotes to int.  This is (nearly) the
@@ -9147,7 +9147,7 @@  resolve_overloaded_builtin (location_t l
 	if (n == 0)
 	  return error_mark_node;
 
-	new_function = built_in_decls[orig_code + exact_log2 (n) + 1];
+	new_function = built_in_set_decl_add (orig_code, exact_log2 (n) + 1);
 	if (!sync_resolve_params (function, new_function, params))
 	  return error_mark_node;
 
Index: gcc/c-family/c-omp.c
===================================================================
--- gcc/c-family/c-omp.c	(.../trunk)	(revision 179369)
+++ gcc/c-family/c-omp.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -77,7 +77,7 @@  c_finish_omp_barrier (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
+  x = built_in_decls (BUILT_IN_GOMP_BARRIER);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
@@ -91,7 +91,7 @@  c_finish_omp_taskwait (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+  x = built_in_decls (BUILT_IN_GOMP_TASKWAIT);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
@@ -105,7 +105,7 @@  c_finish_omp_taskyield (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  x = built_in_decls (BUILT_IN_GOMP_TASKYIELD);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
@@ -260,7 +260,7 @@  c_finish_omp_flush (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+  x = built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
Index: gcc/tree-loop-distribution.c
===================================================================
--- gcc/tree-loop-distribution.c	(.../trunk)	(revision 179369)
+++ gcc/tree-loop-distribution.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -289,7 +289,7 @@  generate_memset_zero (gimple stmt, tree 
   mem = force_gimple_operand (addr_base, &stmts, true, NULL);
   gimple_seq_add_seq (&stmt_list, stmts);
 
-  fn = build_fold_addr_expr (implicit_built_in_decls [BUILT_IN_MEMSET]);
+  fn = build_fold_addr_expr (implicit_built_in_decls (BUILT_IN_MEMSET));
   fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes);
   gimple_seq_add_stmt (&stmt_list, fn_call);
   gsi_insert_seq_after (&bsi, stmt_list, GSI_CONTINUE_LINKING);
Index: gcc/java/class.c
===================================================================
--- gcc/java/class.c	(.../trunk)	(revision 179369)
+++ gcc/java/class.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1266,7 +1266,7 @@  build_static_field_ref (tree fdecl)
       int cpool_index = alloc_constant_fieldref (output_class, fdecl);
       tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl);
       tree test
-        = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2,
+        = build_call_expr (built_in_decls (BUILT_IN_EXPECT), 2,
 			   build2 (EQ_EXPR, boolean_type_node,
 				   cache_entry, null_pointer_node),
 			   boolean_false_node);
Index: gcc/java/decl.c
===================================================================
--- gcc/java/decl.c	(.../trunk)	(revision 179369)
+++ gcc/java/decl.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1135,7 +1135,7 @@  java_init_decl_processing (void)
 
   initialize_builtins ();
 
-  soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
+  soft_fmod_node = built_in_decls (BUILT_IN_FMOD);
 
   parse_version ();
 }
Index: gcc/java/except.c
===================================================================
--- gcc/java/except.c	(.../trunk)	(revision 179369)
+++ gcc/java/except.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -520,7 +520,7 @@  expand_end_java_handler (struct eh_range
 	    type = throwable_type_node;
 	  eh_type = prepare_eh_table_type (type);
 
-	  x = build_call_expr (built_in_decls[BUILT_IN_EH_POINTER],
+	  x = build_call_expr (built_in_decls (BUILT_IN_EH_POINTER),
 				1, integer_zero_node);
 	  x = build2 (MODIFY_EXPR, void_type_node, exc_obj, x);
 	  tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
Index: gcc/java/builtins.c
===================================================================
--- gcc/java/builtins.c	(.../trunk)	(revision 179369)
+++ gcc/java/builtins.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -329,8 +329,8 @@  compareAndSwapInt_builtin (tree method_r
 
       addr = build_addr_sum (int_type_node, obj_arg, offset_arg);
       stmt = build_call_expr 
-			(built_in_decls[BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4],
-			 3, addr, expected_arg, value_arg);
+		       (built_in_decls (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4),
+			3, addr, expected_arg, value_arg);
 
       return build_check_this (stmt, this_arg);
     }
@@ -356,8 +356,8 @@  compareAndSwapLong_builtin (tree method_
 
       addr = build_addr_sum (long_type_node, obj_arg, offset_arg);
       stmt = build_call_expr 
-			(built_in_decls[BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8],
-			 3, addr, expected_arg, value_arg);
+		       (built_in_decls (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8),
+			3, addr, expected_arg, value_arg);
 
       return build_check_this (stmt, this_arg);
     }
@@ -373,7 +373,7 @@  compareAndSwapObject_builtin (tree metho
       || flag_use_atomic_builtins)
   {
     tree addr, stmt;
-    int builtin;
+    enum built_in_function builtin;
 
     UNMARSHAL5 (orig_call);
     builtin = (POINTER_SIZE == 32 
@@ -381,7 +381,7 @@  compareAndSwapObject_builtin (tree metho
 	       : BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8);
 
     addr = build_addr_sum (value_type, obj_arg, offset_arg);
-    stmt = build_call_expr (built_in_decls[builtin],
+    stmt = build_call_expr (built_in_decls (builtin),
 			    3, addr, expected_arg, value_arg);
 
     return build_check_this (stmt, this_arg);
@@ -401,7 +401,7 @@  putVolatile_builtin (tree method_return_
     = fold_convert (build_pointer_type (build_type_variant (value_type, 0, 1)),
 		    addr);
   
-  stmt = build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0);
+  stmt = build_call_expr (built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE), 0);
   modify_stmt = fold_build2 (MODIFY_EXPR, value_type,
 			     build_java_indirect_ref (value_type, addr,
 						      flag_check_references),
@@ -425,7 +425,7 @@  getVolatile_builtin (tree method_return_
     = fold_convert (build_pointer_type (build_type_variant 
 					(method_return_type, 0, 1)), addr);
   
-  stmt = build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0);
+  stmt = build_call_expr (built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE), 0);
   
   tmp = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL, method_return_type);
   DECL_IGNORED_P (tmp) = 1;
@@ -483,8 +483,8 @@  define_builtin (enum built_in_function v
   if (flags & BUILTIN_CONST)
     TREE_READONLY (decl) = 1;
 
-  implicit_built_in_decls[val] = decl;
-  built_in_decls[val] = decl;
+  built_in_set_decl (val, decl);
+  built_in_set_implicit (val, decl);
 }
 
 
@@ -627,7 +627,7 @@  check_for_builtin (tree method, tree cal
 	         with the BC-ABI.  */
 	      if (flag_indirect_dispatch)
 	        return call;
-	      fn = built_in_decls[java_builtins[i].builtin_code];
+	      fn = built_in_decls (java_builtins[i].builtin_code);
 	      if (fn == NULL_TREE)
 		return call;
 	      return java_build_function_call_expr (fn, call);
Index: gcc/java/expr.c
===================================================================
--- gcc/java/expr.c	(.../trunk)	(revision 179369)
+++ gcc/java/expr.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2073,7 +2073,7 @@  static void
 rewrite_arglist_getcaller (VEC(tree,gc) **arglist)
 {
   tree retaddr 
-    = build_call_expr (built_in_decls[BUILT_IN_RETURN_ADDRESS],
+    = build_call_expr (built_in_decls (BUILT_IN_RETURN_ADDRESS),
 		       1, integer_zero_node);
 
   DECL_UNINLINABLE (current_function_decl) = 1;
@@ -2934,7 +2934,7 @@  expand_java_field_op (int is_static, int
 
       if (TREE_THIS_VOLATILE (field_decl))
 	java_add_stmt
-	  (build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0));
+	  (build_call_expr (built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE), 0));
       	  
       java_add_stmt (modify_expr);
     }
@@ -2953,7 +2953,7 @@  expand_java_field_op (int is_static, int
 
       if (TREE_THIS_VOLATILE (field_decl))
 	java_add_stmt 
-	  (build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0));
+	  (build_call_expr (built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE), 0));
 
       push_value (temp);
     }      
Index: gcc/tree-ssa-strlen.c
===================================================================
--- gcc/tree-ssa-strlen.c	(.../trunk)	(revision 179369)
+++ gcc/tree-ssa-strlen.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -397,7 +397,7 @@  get_string_length (strinfo si)
       callee = gimple_call_fndecl (stmt);
       gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
       lhs = gimple_call_lhs (stmt);
-      gcc_assert (implicit_built_in_decls[BUILT_IN_STRCPY] != NULL_TREE);
+      gcc_assert (implicit_built_in_decls (BUILT_IN_STRCPY) != NULL_TREE);
       /* unshare_strinfo is intentionally not called here.  The (delayed)
 	 transformation of strcpy or strcat into stpcpy is done at the place
 	 of the former strcpy/strcat call and so can affect all the strinfos
@@ -409,7 +409,7 @@  get_string_length (strinfo si)
 	case BUILT_IN_STRCAT:
 	case BUILT_IN_STRCAT_CHK:
 	  gsi = gsi_for_stmt (stmt);
-	  fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+	  fn = implicit_built_in_decls (BUILT_IN_STRLEN);
 	  gcc_assert (lhs == NULL_TREE);
 	  lhs_var = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
 	  add_referenced_var (lhs_var);
@@ -434,9 +434,9 @@  get_string_length (strinfo si)
 	case BUILT_IN_STRCPY:
 	case BUILT_IN_STRCPY_CHK:
 	  if (gimple_call_num_args (stmt) == 2)
-	    fn = implicit_built_in_decls[BUILT_IN_STPCPY];
+	    fn = implicit_built_in_decls (BUILT_IN_STPCPY);
 	  else
-	    fn = built_in_decls[BUILT_IN_STPCPY_CHK];
+	    fn = built_in_decls (BUILT_IN_STPCPY_CHK);
 	  gcc_assert (lhs == NULL_TREE);
 	  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	    {
@@ -1066,7 +1066,7 @@  handle_builtin_strcpy (enum built_in_fun
       {
       case BUILT_IN_STRCPY:
       case BUILT_IN_STRCPY_CHK:
-	if (implicit_built_in_decls[BUILT_IN_STPCPY] == NULL_TREE
+	if (implicit_built_in_decls (BUILT_IN_STPCPY) == NULL_TREE
 	    || lhs != NULL_TREE)
 	  return;
 	break;
@@ -1150,12 +1150,12 @@  handle_builtin_strcpy (enum built_in_fun
   switch (bcode)
     {
     case BUILT_IN_STRCPY:
-      fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+      fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
       if (lhs)
 	VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
       break;
     case BUILT_IN_STRCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+      fn = built_in_decls (BUILT_IN_MEMCPY_CHK);
       if (lhs)
 	VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
       break;
@@ -1163,7 +1163,7 @@  handle_builtin_strcpy (enum built_in_fun
       /* This would need adjustment of the lhs (subtract one),
 	 or detection that the trailing '\0' doesn't need to be
 	 written, if it will be immediately overwritten.
-      fn = built_in_decls[BUILT_IN_MEMPCPY];  */
+      fn = built_in_decls (BUILT_IN_MEMPCPY);  */
       if (lhs)
 	{
 	  dsi->endptr = lhs;
@@ -1174,7 +1174,7 @@  handle_builtin_strcpy (enum built_in_fun
       /* This would need adjustment of the lhs (subtract one),
 	 or detection that the trailing '\0' doesn't need to be
 	 written, if it will be immediately overwritten.
-      fn = built_in_decls[BUILT_IN_MEMPCPY_CHK];  */
+      fn = built_in_decls (BUILT_IN_MEMPCPY_CHK);  */
       if (lhs)
 	{
 	  dsi->endptr = lhs;
@@ -1396,7 +1396,7 @@  handle_builtin_strcat (enum built_in_fun
 	 with length endptr - p if we need to compute the length
 	 later on.  Don't do this transformation if we don't need
 	 it.  */
-      if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
+      if (implicit_built_in_decls (BUILT_IN_STPCPY) != NULL_TREE
 	  && lhs == NULL_TREE)
 	{
 	  if (didx == 0)
@@ -1456,7 +1456,7 @@  handle_builtin_strcat (enum built_in_fun
   else
     {
       dsi->length = NULL;
-      if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
+      if (implicit_built_in_decls (BUILT_IN_STPCPY) != NULL_TREE
 	  && lhs == NULL_TREE)
 	dsi->dont_invalidate = true;
     }
@@ -1477,15 +1477,15 @@  handle_builtin_strcat (enum built_in_fun
     {
     case BUILT_IN_STRCAT:
       if (srclen != NULL_TREE)
-	fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+	fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
       else
-	fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+	fn = implicit_built_in_decls (BUILT_IN_STRCPY);
       break;
     case BUILT_IN_STRCAT_CHK:
       if (srclen != NULL_TREE)
-	fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+	fn = built_in_decls (BUILT_IN_MEMCPY_CHK);
       else
-	fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+	fn = built_in_decls (BUILT_IN_STRCPY_CHK);
       objsz = gimple_call_arg (stmt, 2);
       break;
     default:
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(.../trunk)	(revision 179369)
+++ gcc/tree.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -6864,6 +6864,7 @@  iterative_hash_expr (const_tree t, hashv
   int i;
   enum tree_code code;
   char tclass;
+  tree bfn;
 
   if (t == NULL_TREE)
     return iterative_hash_hashval_t (0, val);
@@ -6942,9 +6943,9 @@  iterative_hash_expr (const_tree t, hashv
 	 or front end builtins, since the function code is overloaded in those
 	 cases.  */
       if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
-	  && built_in_decls[DECL_FUNCTION_CODE (t)])
+	  && (bfn = built_in_decls (DECL_FUNCTION_CODE (t))) != NULL_TREE)
 	{
-	  t = built_in_decls[DECL_FUNCTION_CODE (t)];
+	  t = bfn;
 	  code = TREE_CODE (t);
 	}
       /* FALL THROUGH */
@@ -9429,8 +9430,8 @@  local_define_builtin (const char *name, 
     DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
 					NULL, DECL_ATTRIBUTES (decl));
 
-  built_in_decls[code] = decl;
-  implicit_built_in_decls[code] = decl;
+  built_in_set_decl (code, decl);
+  built_in_set_implicit (code, decl);
 }
 
 /* Call this function after instantiating all builtins that the language
@@ -9442,22 +9443,22 @@  build_common_builtin_nodes (void)
 {
   tree tmp, ftype;
 
-  if (built_in_decls[BUILT_IN_MEMCPY] == NULL
-      || built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+  if (built_in_decls (BUILT_IN_MEMCPY) == NULL
+      || built_in_decls (BUILT_IN_MEMMOVE) == NULL)
     {
       ftype = build_function_type_list (ptr_type_node,
 					ptr_type_node, const_ptr_type_node,
 					size_type_node, NULL_TREE);
 
-      if (built_in_decls[BUILT_IN_MEMCPY] == NULL)
+      if (built_in_decls (BUILT_IN_MEMCPY) == NULL)
 	local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
 			      "memcpy", ECF_NOTHROW | ECF_LEAF);
-      if (built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+      if (built_in_decls (BUILT_IN_MEMMOVE) == NULL)
 	local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
 			      "memmove", ECF_NOTHROW | ECF_LEAF);
     }
 
-  if (built_in_decls[BUILT_IN_MEMCMP] == NULL)
+  if (built_in_decls (BUILT_IN_MEMCMP) == NULL)
     {
       ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
 					const_ptr_type_node, size_type_node,
@@ -9466,7 +9467,7 @@  build_common_builtin_nodes (void)
 			    "memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
     }
 
-  if (built_in_decls[BUILT_IN_MEMSET] == NULL)
+  if (built_in_decls (BUILT_IN_MEMSET) == NULL)
     {
       ftype = build_function_type_list (ptr_type_node,
 					ptr_type_node, integer_type_node,
@@ -9475,7 +9476,7 @@  build_common_builtin_nodes (void)
 			    "memset", ECF_NOTHROW | ECF_LEAF);
     }
 
-  if (built_in_decls[BUILT_IN_ALLOCA] == NULL)
+  if (built_in_decls (BUILT_IN_ALLOCA) == NULL)
     {
       ftype = build_function_type_list (ptr_type_node,
 					size_type_node, NULL_TREE);
@@ -9485,7 +9486,7 @@  build_common_builtin_nodes (void)
 
   /* If we're checking the stack, `alloca' can throw.  */
   if (flag_stack_check)
-    TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
+    TREE_NOTHROW (built_in_decls (BUILT_IN_ALLOCA)) = 0;
 
   ftype = build_function_type_list (void_type_node,
 				    ptr_type_node, ptr_type_node,
@@ -9551,7 +9552,7 @@  build_common_builtin_nodes (void)
 			 ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
 			ECF_NORETURN);
 
-  if (built_in_decls[BUILT_IN_RETURN_ADDRESS] == NULL_TREE)
+  if (built_in_decls (BUILT_IN_RETURN_ADDRESS) == NULL_TREE)
     {
       ftype = build_function_type_list (ptr_type_node, integer_type_node,
 					NULL_TREE);
@@ -9561,16 +9562,16 @@  build_common_builtin_nodes (void)
 			    ECF_NOTHROW);
     }
 
-  if (built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER] == NULL_TREE
-      || built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT] == NULL_TREE)
+  if (built_in_decls (BUILT_IN_PROFILE_FUNC_ENTER) == NULL_TREE
+      || built_in_decls (BUILT_IN_PROFILE_FUNC_EXIT) == NULL_TREE)
     {
       ftype = build_function_type_list (void_type_node, ptr_type_node,
 					ptr_type_node, NULL_TREE);
-      if (built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER] == NULL_TREE)
+      if (built_in_decls (BUILT_IN_PROFILE_FUNC_ENTER) == NULL_TREE)
 	local_define_builtin ("__cyg_profile_func_enter", ftype,
 			      BUILT_IN_PROFILE_FUNC_ENTER,
 			      "__cyg_profile_func_enter", 0);
-      if (built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT] == NULL_TREE)
+      if (built_in_decls (BUILT_IN_PROFILE_FUNC_EXIT) == NULL_TREE)
 	local_define_builtin ("__cyg_profile_func_exit", ftype,
 			      BUILT_IN_PROFILE_FUNC_EXIT,
 			      "__cyg_profile_func_exit", 0);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(.../trunk)	(revision 179369)
+++ gcc/tree.h	(.../branches/ibm/builtin)	(revision 179396)
@@ -336,9 +336,6 @@  extern const char * built_in_names[(int)
 #define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
 #define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL
 
-/* An array of _DECL trees for the above.  */
-extern GTY(()) tree built_in_decls[(int) END_BUILTINS];
-extern GTY(()) tree implicit_built_in_decls[(int) END_BUILTINS];
 
 /* In an OMP_CLAUSE node.  */
 
@@ -599,6 +596,9 @@  struct GTY(()) tree_common {
        CALL_ALLOCA_FOR_VAR_P in
            CALL_EXPR
 
+       IDENTIFIER_LAZY_BUILTIN_P in
+	   IDENTIFIER_NODE
+
    side_effects_flag:
 
        TREE_SIDE_EFFECTS in
@@ -5914,4 +5914,58 @@  is_lang_specific (tree t)
 /* In gimple-low.c.  */
 extern bool block_may_fallthru (const_tree);
 
+
+/* Functional interface to the builtin functions.  */
+#define BUILT_IN_DECL		0
+#define BUILT_IN_IMPLICIT	1
+#define BUILT_IN_NUM		2
+
+extern GTY(()) tree built_in_info[(int)END_BUILTINS][BUILT_IN_NUM];
+
+/* Valid builtin number.  */
+#define BUILT_IN_VALID_P(FNCODE) \
+  (IN_RANGE ((int)FNCODE, ((int)BUILT_IN_NONE) + 1, ((int) END_BUILTINS) - 1))
+
+/* Return the tree node for a builtin function or NULL, possibly
+   creating the tree node.  */
+static inline tree
+built_in_decls (enum built_in_function fncode)
+{
+  gcc_assert (BUILT_IN_VALID_P (fncode));
+  return built_in_info[(int)fncode][BUILT_IN_DECL];
+}
+
+/* Return the tree node for a builtin function or NULL, possibly
+   creating the tree node.  */
+static inline tree
+implicit_built_in_decls (enum built_in_function fncode)
+{
+  gcc_assert (BUILT_IN_VALID_P (fncode));
+  return built_in_info[(int)fncode][BUILT_IN_IMPLICIT];
+}
+
+/* Return the tree node for a builtin function or NULL, indexing into the
+   array.  */
+static inline tree
+built_in_set_decl_add (enum built_in_function fncode, int addend)
+{
+  return built_in_decls ((enum built_in_function)(((int)fncode) + addend));
+}
+
+/* Initialize an explicit builtin function.  */
+static inline void
+built_in_set_decl (enum built_in_function fncode, tree decl)
+{
+  gcc_assert (BUILT_IN_VALID_P (fncode));
+  built_in_info[(int)fncode][BUILT_IN_DECL] = decl;
+}
+
+/* Initialize an implicit builtin function.  */
+static inline void
+built_in_set_implicit (enum built_in_function fncode, tree implicit)
+{
+  gcc_assert (BUILT_IN_VALID_P (fncode));
+  built_in_info[(int)fncode][BUILT_IN_IMPLICIT] = implicit;
+}
+
 #endif  /* GCC_TREE_H  */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(.../trunk)	(revision 179369)
+++ gcc/builtins.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -75,11 +75,7 @@  const char * built_in_names[(int) END_BU
 
 /* Setup an array of _DECL trees, make sure each element is
    initialized to NULL_TREE.  */
-tree built_in_decls[(int) END_BUILTINS];
-/* Declarations used when constructing the builtin implicitly in the compiler.
-   It may be NULL_TREE when this is invalid (for instance runtime is not
-   required to implement the function call in all cases).  */
-tree implicit_built_in_decls[(int) END_BUILTINS];
+tree built_in_info[(int)END_BUILTINS][BUILT_IN_NUM];
 
 static const char *c_getstr (tree);
 static rtx c_readstr (const char *, enum machine_mode);
@@ -1791,17 +1787,15 @@  expand_builtin_classify_type (tree exp)
   fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
   fcodel = BUILT_IN_MATHFN##L_R ; break;
 
-/* Return mathematic function equivalent to FN but operating directly
-   on TYPE, if available.  If IMPLICIT is true find the function in
-   implicit_built_in_decls[], otherwise use built_in_decls[].  If we
-   can't do the conversion, return zero.  */
+/* Return mathematic function equivalent to FN but operating directly on TYPE,
+   if available.  If IMPLICIT is true find the function as an implicit builtin
+   function instead of a normal builtin function.  If we can't do the
+   conversion, return zero.  */
 
 static tree
 mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
 {
-  tree const *const fn_arr
-    = implicit ? implicit_built_in_decls : built_in_decls;
-  enum built_in_function fcode, fcodef, fcodel;
+  enum built_in_function fcode, fcodef, fcodel, fcode2;
 
   switch (fn)
     {
@@ -1898,13 +1892,17 @@  mathfn_built_in_1 (tree type, enum built
       }
 
   if (TYPE_MAIN_VARIANT (type) == double_type_node)
-    return fn_arr[fcode];
+    fcode2 = fcode;
   else if (TYPE_MAIN_VARIANT (type) == float_type_node)
-    return fn_arr[fcodef];
+    fcode2 = fcodef;
   else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
-    return fn_arr[fcodel];
+    fcode2 = fcodel;
   else
     return NULL_TREE;
+
+  return ((implicit)
+	  ? implicit_built_in_decls (fcode2)
+	  : built_in_decls (fcode2));
 }
 
 /* Like mathfn_built_in_1(), but always use the implicit array.  */
@@ -2552,16 +2550,18 @@  expand_builtin_cexpi (tree exp, rtx targ
       tree call, fn = NULL_TREE;
       tree top1, top2;
       rtx op1a, op2a;
+      enum built_in_function fcode;
 
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
-	fn = built_in_decls[BUILT_IN_SINCOSF];
+	fcode = BUILT_IN_SINCOSF;
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
-	fn = built_in_decls[BUILT_IN_SINCOS];
+	fcode = BUILT_IN_SINCOS;
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
-	fn = built_in_decls[BUILT_IN_SINCOSL];
+	fcode = BUILT_IN_SINCOSL;
       else
 	gcc_unreachable ();
 
+      fn = built_in_decls (fcode);
       op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
       op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
       op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
@@ -2578,16 +2578,19 @@  expand_builtin_cexpi (tree exp, rtx targ
     {
       tree call, fn = NULL_TREE, narg;
       tree ctype = build_complex_type (type);
+      enum built_in_function fcode;
 
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
-	fn = built_in_decls[BUILT_IN_CEXPF];
+	fcode = BUILT_IN_CEXPF;
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
-	fn = built_in_decls[BUILT_IN_CEXP];
+	fcode = BUILT_IN_CEXP;
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
-	fn = built_in_decls[BUILT_IN_CEXPL];
+	fcode = BUILT_IN_CEXPL;
       else
 	gcc_unreachable ();
 
+      fn = built_in_decls (fcode);
+
       /* If we don't have a decl for cexp create one.  This is the
 	 friendliest fallback if the user calls __builtin_cexpi
 	 without full target C99 function support.  */
@@ -3129,9 +3132,9 @@  expand_builtin_mempcpy_args (tree dest, 
 			     rtx target, enum machine_mode mode, int endp)
 {
     /* If return value is ignored, transform mempcpy into memcpy.  */
-  if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY])
+  if (target == const0_rtx && implicit_built_in_decls (BUILT_IN_MEMCPY))
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+      tree fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
       tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
 					   dest, src, len);
       return expand_expr (result, target, mode, EXPAND_NORMAL);
@@ -3292,9 +3295,9 @@  expand_builtin_stpcpy (tree exp, rtx tar
   src = CALL_EXPR_ARG (exp, 1);
 
   /* If return value is ignored, transform stpcpy into strcpy.  */
-  if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY])
+  if (target == const0_rtx && implicit_built_in_decls (BUILT_IN_STRCPY))
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = implicit_built_in_decls (BUILT_IN_STRCPY);
       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
       return expand_expr (result, target, mode, EXPAND_NORMAL);
     }
@@ -4353,7 +4356,7 @@  gimplify_va_arg_expr (tree *expr_p, gimp
 	 expression to exit or longjmp.  */
       gimplify_and_add (valist, pre_p);
       t = build_call_expr_loc (loc,
-			       implicit_built_in_decls[BUILT_IN_TRAP], 0);
+			       implicit_built_in_decls (BUILT_IN_TRAP), 0);
       gimplify_and_add (t, pre_p);
 
       /* This is dead code, but go ahead and finish so that the
@@ -5113,7 +5116,7 @@  expand_builtin_sync_operation (enum mach
 	  if (warned_f_a_n)
 	    break;
 
-	  fndecl = implicit_built_in_decls[BUILT_IN_SYNC_FETCH_AND_NAND_N];
+	  fndecl = implicit_built_in_decls (BUILT_IN_SYNC_FETCH_AND_NAND_N);
 	  inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
 	  warned_f_a_n = true;
 	  break;
@@ -5127,7 +5130,7 @@  expand_builtin_sync_operation (enum mach
 	  if (warned_n_a_f)
 	    break;
 
-	  fndecl = implicit_built_in_decls[BUILT_IN_SYNC_NAND_AND_FETCH_N];
+	  fndecl = implicit_built_in_decls (BUILT_IN_SYNC_NAND_AND_FETCH_N);
 	  inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
 	  warned_n_a_f = true;
 	  break;
@@ -6232,7 +6235,7 @@  build_builtin_expect_predicate (location
 {
   tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
 
-  fn = built_in_decls[BUILT_IN_EXPECT];
+  fn = built_in_decls (BUILT_IN_EXPECT);
   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
   ret_type = TREE_TYPE (TREE_TYPE (fn));
   pred_type = TREE_VALUE (arg_types);
@@ -8024,7 +8027,7 @@  fold_builtin_memory_op (location_t loc, 
 		  && (MIN (src_align, dest_align) / BITS_PER_UNIT
 		      >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
 	    {
-	      tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+	      tree fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
 	      if (!fn)
 		return NULL_TREE;
               return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8083,7 +8086,7 @@  fold_builtin_memory_op (location_t loc, 
 	      else
 		return NULL_TREE;
 
-	      fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+	      fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
 	      if (!fn)
 		return NULL_TREE;
 	      return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8102,7 +8105,7 @@  fold_builtin_memory_op (location_t loc, 
 	      if (!refs_may_alias_p_1 (&destr, &srcr, false))
 		{
 		  tree fn;
-		  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+		  fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
 		  if (!fn)
 		    return NULL_TREE;
 		  return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8277,7 +8280,7 @@  fold_builtin_strcpy (location_t loc, tre
   if (optimize_function_for_size_p (cfun))
     return NULL_TREE;
 
-  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -8315,7 +8318,7 @@  fold_builtin_stpcpy (location_t loc, tre
       && !integer_zerop (len))
     return NULL_TREE;
 
-  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -8372,7 +8375,7 @@  fold_builtin_strncpy (location_t loc, tr
     return NULL_TREE;
 
   /* OK transform into builtin memcpy.  */
-  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  fn = implicit_built_in_decls (BUILT_IN_MEMCPY);
   if (!fn)
     return NULL_TREE;
   return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
@@ -9193,7 +9196,7 @@  fold_builtin_interclass_mathfn (location
     CASE_FLT_FN (BUILT_IN_ISINF):
       {
 	/* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
-	tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
+	tree const isgr_fn = built_in_decls (BUILT_IN_ISGREATER);
 	tree const type = TREE_TYPE (arg);
 	REAL_VALUE_TYPE r;
 	char buf[128];
@@ -9209,7 +9212,7 @@  fold_builtin_interclass_mathfn (location
     case BUILT_IN_ISFINITE:
       {
 	/* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
-	tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
+	tree const isle_fn = built_in_decls (BUILT_IN_ISLESSEQUAL);
 	tree const type = TREE_TYPE (arg);
 	REAL_VALUE_TYPE r;
 	char buf[128];
@@ -9232,8 +9235,8 @@  fold_builtin_interclass_mathfn (location
       {
 	/* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
 	   islessequal(fabs(x),DBL_MAX).  */
-	tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
-	tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
+	tree const isle_fn = built_in_decls (BUILT_IN_ISLESSEQUAL);
+	tree const isge_fn = built_in_decls (BUILT_IN_ISGREATEREQUAL);
 	tree const type = TREE_TYPE (arg);
 	REAL_VALUE_TYPE rmax, rmin;
 	char buf[128];
@@ -9294,7 +9297,7 @@  fold_builtin_classify (location_t loc, t
 	   1.  So e.g. "if (isinf_sign(x))" would be folded to just
 	   "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
 	tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
-	tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
+	tree isinf_fn = built_in_decls (BUILT_IN_ISINF);
 	tree tmp = NULL_TREE;
 
 	arg = builtin_save_expr (arg);
@@ -10017,7 +10020,7 @@  fold_builtin_2 (location_t loc, tree fnd
     case BUILT_IN_STPCPY:
       if (ignore)
 	{
-	  tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+	  tree fn = implicit_built_in_decls (BUILT_IN_STRCPY);
 	  if (!fn)
 	    break;
 
@@ -10817,7 +10820,7 @@  fold_builtin_strstr (location_t loc, tre
       if (p2[1] != '\0')
 	return NULL_TREE;
 
-      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+      fn = implicit_built_in_decls (BUILT_IN_STRCHR);
       if (!fn)
 	return NULL_TREE;
 
@@ -10937,7 +10940,7 @@  fold_builtin_strrchr (location_t loc, tr
       if (! integer_zerop (s2))
 	return NULL_TREE;
 
-      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+      fn = implicit_built_in_decls (BUILT_IN_STRCHR);
       if (!fn)
 	return NULL_TREE;
 
@@ -11001,7 +11004,7 @@  fold_builtin_strpbrk (location_t loc, tr
       if (p2[1] != '\0')
 	return NULL_TREE;  /* Really call strpbrk.  */
 
-      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+      fn = implicit_built_in_decls (BUILT_IN_STRCHR);
       if (!fn)
 	return NULL_TREE;
 
@@ -11048,8 +11051,8 @@  fold_builtin_strcat (location_t loc ATTR
 	{
 	  /* See if we can store by pieces into (dst + strlen(dst)).  */
 	  tree newdst, call;
-	  tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
-	  tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+	  tree strlen_fn = implicit_built_in_decls (BUILT_IN_STRLEN);
+	  tree strcpy_fn = implicit_built_in_decls (BUILT_IN_STRCPY);
 
 	  if (!strlen_fn || !strcpy_fn)
 	    return NULL_TREE;
@@ -11122,7 +11125,7 @@  fold_builtin_strncat (location_t loc, tr
       if (TREE_CODE (len) == INTEGER_CST && p
 	  && compare_tree_int (len, strlen (p)) >= 0)
 	{
-	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
+	  tree fn = implicit_built_in_decls (BUILT_IN_STRCAT);
 
 	  /* If the replacement _DECL isn't initialized, don't do the
 	     transformation.  */
@@ -11227,7 +11230,7 @@  fold_builtin_strcspn (location_t loc, tr
       /* If the second argument is "", return __builtin_strlen(s1).  */
       if (p2 && *p2 == '\0')
 	{
-	  tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+	  tree fn = implicit_built_in_decls (BUILT_IN_STRLEN);
 
 	  /* If the replacement _DECL isn't initialized, don't do the
 	     transformation.  */
@@ -11253,10 +11256,10 @@  fold_builtin_fputs (location_t loc, tree
 {
   /* If we're using an unlocked function, assume the other unlocked
      functions exist explicitly.  */
-  tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
-    : implicit_built_in_decls[BUILT_IN_FPUTC];
-  tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
-    : implicit_built_in_decls[BUILT_IN_FWRITE];
+  tree const fn_fputc = unlocked ? built_in_decls (BUILT_IN_FPUTC_UNLOCKED)
+    : implicit_built_in_decls (BUILT_IN_FPUTC);
+  tree const fn_fwrite = unlocked ? built_in_decls (BUILT_IN_FWRITE_UNLOCKED)
+    : implicit_built_in_decls (BUILT_IN_FWRITE);
 
   /* If the return value is used, don't do the transformation.  */
   if (!ignore)
@@ -11450,7 +11453,7 @@  fold_builtin_sprintf (location_t loc, tr
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = implicit_built_in_decls (BUILT_IN_STRCPY);
 
       if (!fn)
 	return NULL_TREE;
@@ -11470,7 +11473,7 @@  fold_builtin_sprintf (location_t loc, tr
   else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
     {
       tree fn;
-      fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      fn = implicit_built_in_decls (BUILT_IN_STRCPY);
 
       if (!fn)
 	return NULL_TREE;
@@ -11491,9 +11494,8 @@  fold_builtin_sprintf (location_t loc, tr
 
   if (call && retval)
     {
-      retval = fold_convert_loc
-	(loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
-	 retval);
+      tree fn = implicit_built_in_decls (BUILT_IN_SPRINTF);
+      retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
     }
   else
@@ -11545,7 +11547,7 @@  fold_builtin_snprintf (location_t loc, t
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = implicit_built_in_decls (BUILT_IN_STRCPY);
       size_t len = strlen (fmt_str);
 
       /* Don't optimize snprintf (buf, 4, "abc", ptr++).  */
@@ -11577,7 +11579,7 @@  fold_builtin_snprintf (location_t loc, t
   /* If the format is "%s", use strcpy if the result isn't used.  */
   else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = implicit_built_in_decls (BUILT_IN_STRCPY);
       unsigned HOST_WIDE_INT origlen;
 
       /* Don't crash on snprintf (str1, cst, "%s").  */
@@ -11612,7 +11614,7 @@  fold_builtin_snprintf (location_t loc, t
 
   if (call && retval)
     {
-      tree fn = built_in_decls[BUILT_IN_SNPRINTF];
+      tree fn = built_in_decls (BUILT_IN_SNPRINTF);
       retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
     }
@@ -11700,16 +11702,16 @@  expand_builtin_memory_chk (tree exp, rtx
       switch (fcode)
 	{
 	case BUILT_IN_MEMCPY_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMCPY];
+	  fn = built_in_decls (BUILT_IN_MEMCPY);
 	  break;
 	case BUILT_IN_MEMPCPY_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMPCPY];
+	  fn = built_in_decls (BUILT_IN_MEMPCPY);
 	  break;
 	case BUILT_IN_MEMMOVE_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMMOVE];
+	  fn = built_in_decls (BUILT_IN_MEMMOVE);
 	  break;
 	case BUILT_IN_MEMSET_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMSET];
+	  fn = built_in_decls (BUILT_IN_MEMSET);
 	  break;
 	default:
 	  break;
@@ -11761,7 +11763,7 @@  expand_builtin_memory_chk (tree exp, rtx
 	     normal __memcpy_chk.  */
 	  if (readonly_data_expr (src))
 	    {
-	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+	      tree fn = built_in_decls (BUILT_IN_MEMCPY_CHK);
 	      if (!fn)
 		return NULL_RTX;
 	      fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
@@ -12025,7 +12027,7 @@  fold_builtin_memory_chk (location_t loc,
 		{
 		  /* (void) __mempcpy_chk () can be optimized into
 		     (void) __memcpy_chk ().  */
-		  fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+		  fn = built_in_decls (BUILT_IN_MEMCPY_CHK);
 		  if (!fn)
 		    return NULL_TREE;
 
@@ -12047,16 +12049,16 @@  fold_builtin_memory_chk (location_t loc,
   switch (fcode)
     {
     case BUILT_IN_MEMCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMCPY];
+      fn = built_in_decls (BUILT_IN_MEMCPY);
       break;
     case BUILT_IN_MEMPCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMPCPY];
+      fn = built_in_decls (BUILT_IN_MEMPCPY);
       break;
     case BUILT_IN_MEMMOVE_CHK:
-      fn = built_in_decls[BUILT_IN_MEMMOVE];
+      fn = built_in_decls (BUILT_IN_MEMMOVE);
       break;
     case BUILT_IN_MEMSET_CHK:
-      fn = built_in_decls[BUILT_IN_MEMSET];
+      fn = built_in_decls (BUILT_IN_MEMSET);
       break;
     default:
       break;
@@ -12111,7 +12113,7 @@  fold_builtin_stxcpy_chk (location_t loc,
 
 		  /* If return value of __stpcpy_chk is ignored,
 		     optimize into __strcpy_chk.  */
-		  fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+		  fn = built_in_decls (BUILT_IN_STRCPY_CHK);
 		  if (!fn)
 		    return NULL_TREE;
 
@@ -12123,7 +12125,7 @@  fold_builtin_stxcpy_chk (location_t loc,
 
 	      /* If c_strlen returned something, but not a constant,
 		 transform __strcpy_chk into __memcpy_chk.  */
-	      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+	      fn = built_in_decls (BUILT_IN_MEMCPY_CHK);
 	      if (!fn)
 		return NULL_TREE;
 
@@ -12141,8 +12143,8 @@  fold_builtin_stxcpy_chk (location_t loc,
     }
 
   /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
-  fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
-		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
+  fn = built_in_decls (fcode == BUILT_IN_STPCPY_CHK
+		       ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -12186,7 +12188,7 @@  fold_builtin_strncpy_chk (location_t loc
     }
 
   /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
-  fn = built_in_decls[BUILT_IN_STRNCPY];
+  fn = built_in_decls (BUILT_IN_STRNCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -12217,7 +12219,7 @@  fold_builtin_strcat_chk (location_t loc,
     return NULL_TREE;
 
   /* If __builtin_strcat_chk is used, assume strcat is available.  */
-  fn = built_in_decls[BUILT_IN_STRCAT];
+  fn = built_in_decls (BUILT_IN_STRCAT);
   if (!fn)
     return NULL_TREE;
 
@@ -12259,7 +12261,7 @@  fold_builtin_strncat_chk (location_t loc
 	  && ! tree_int_cst_lt (len, src_len))
 	{
 	  /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
-	  fn = built_in_decls[BUILT_IN_STRCAT_CHK];
+	  fn = built_in_decls (BUILT_IN_STRCAT_CHK);
 	  if (!fn)
 	    return NULL_TREE;
 
@@ -12269,7 +12271,7 @@  fold_builtin_strncat_chk (location_t loc
     }
 
   /* If __builtin_strncat_chk is used, assume strncat is available.  */
-  fn = built_in_decls[BUILT_IN_STRNCAT];
+  fn = built_in_decls (BUILT_IN_STRNCAT);
   if (!fn)
     return NULL_TREE;
 
@@ -12360,8 +12362,8 @@  fold_builtin_sprintf_chk_1 (location_t l
     }
 
   /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
-  fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
-		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
+  fn = built_in_decls (fcode == BUILT_IN_VSPRINTF_CHK
+		       ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
   if (!fn)
     return NULL_TREE;
 
@@ -12449,8 +12451,8 @@  fold_builtin_snprintf_chk_1 (location_t 
 
   /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
      available.  */
-  fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
-		      ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
+  fn = built_in_decls (fcode == BUILT_IN_VSNPRINTF_CHK
+		       ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
   if (!fn)
     return NULL_TREE;
 
@@ -12504,13 +12506,13 @@  fold_builtin_printf (location_t loc, tre
     {
       /* If we're using an unlocked function, assume the other
 	 unlocked functions exist explicitly.  */
-      fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
-      fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
+      fn_putchar = built_in_decls (BUILT_IN_PUTCHAR_UNLOCKED);
+      fn_puts = built_in_decls (BUILT_IN_PUTS_UNLOCKED);
     }
   else
     {
-      fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
-      fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
+      fn_putchar = implicit_built_in_decls (BUILT_IN_PUTCHAR);
+      fn_puts = implicit_built_in_decls (BUILT_IN_PUTS);
     }
 
   if (!init_target_chars ())
@@ -12655,13 +12657,13 @@  fold_builtin_fprintf (location_t loc, tr
     {
       /* If we're using an unlocked function, assume the other
 	 unlocked functions exist explicitly.  */
-      fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
-      fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
+      fn_fputc = built_in_decls (BUILT_IN_FPUTC_UNLOCKED);
+      fn_fputs = built_in_decls (BUILT_IN_FPUTS_UNLOCKED);
     }
   else
     {
-      fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
-      fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
+      fn_fputc = implicit_built_in_decls (BUILT_IN_FPUTC);
+      fn_fputs = implicit_built_in_decls (BUILT_IN_FPUTS);
     }
 
   if (!init_target_chars ())
@@ -13463,9 +13465,9 @@  fold_call_stmt (gimple stmt, bool ignore
   return NULL_TREE;
 }
 
-/* Look up the function in built_in_decls that corresponds to DECL
-   and set ASMSPEC as its user assembler name.  DECL must be a
-   function decl that declares a builtin.  */
+/* Look up the function in built_in_decl_info that corresponds to DECL and set
+   ASMSPEC as its user assembler name.  DECL must be a function decl that
+   declares a builtin.  */
 
 void
 set_builtin_user_assembler_name (tree decl, const char *asmspec)
@@ -13475,7 +13477,7 @@  set_builtin_user_assembler_name (tree de
 	      && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
 	      && asmspec != 0);
 
-  builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
+  builtin = built_in_decls (DECL_FUNCTION_CODE (decl));
   set_user_assembler_name (builtin, asmspec);
   switch (DECL_FUNCTION_CODE (decl))
     {
Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c	(.../trunk)	(revision 179369)
+++ gcc/tree-emutls.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -387,7 +387,7 @@  emutls_common_1 (tree tls_decl, tree con
 
   word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
 
-  x = build_call_expr (built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON], 4,
+  x = build_call_expr (built_in_decls (BUILT_IN_EMUTLS_REGISTER_COMMON), 4,
 		       build_fold_addr_expr (control_decl),
 		       fold_convert (word_type_node,
 				     DECL_SIZE_UNIT (tls_decl)),
@@ -622,7 +622,7 @@  lower_emutls_function_body (struct cgrap
   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
 
   d.cfun_node = node;
-  d.builtin_decl = built_in_decls[BUILT_IN_EMUTLS_GET_ADDRESS];
+  d.builtin_decl = built_in_decls (BUILT_IN_EMUTLS_GET_ADDRESS);
   /* This is where we introduce the declaration to the IL and so we have to
      create a node for it.  */
   d.builtin_node = cgraph_get_create_node (d.builtin_decl);
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c	(.../trunk)	(revision 179369)
+++ gcc/omp-low.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2059,7 +2059,7 @@  scan_omp (gimple_seq body, omp_context *
 static tree
 build_omp_barrier (void)
 {
-  return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
+  return build_call_expr (built_in_decls (BUILT_IN_GOMP_BARRIER), 0);
 }
 
 /* If a context was created for STMT when it was scanned, return it.  */
@@ -2309,8 +2309,8 @@  lower_rec_input_clauses (tree clauses, g
 		  x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
 
 		  /* void *tmp = __builtin_alloca */
-		  stmt
-		    = gimple_build_call (built_in_decls[BUILT_IN_ALLOCA], 1, x);
+		  stmt = gimple_build_call (built_in_decls (BUILT_IN_ALLOCA),
+					    1, x);
 		  tmp = create_tmp_var_raw (ptr_type_node, NULL);
 		  gimple_add_tmp_var (tmp);
 		  gimple_call_set_lhs (stmt, tmp);
@@ -2355,7 +2355,8 @@  lower_rec_input_clauses (tree clauses, g
 	      else
 		{
 		  x = build_call_expr_loc (clause_loc,
-				       built_in_decls[BUILT_IN_ALLOCA], 1, x);
+					   built_in_decls (BUILT_IN_ALLOCA),
+					   1, x);
 		}
 
 	      x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
@@ -2493,7 +2494,7 @@  lower_rec_input_clauses (tree clauses, g
      but it certainly is to C++ operator=.  */
   if (copyin_seq)
     {
-      x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+      x = build_call_expr (built_in_decls (BUILT_IN_OMP_GET_THREAD_NUM), 0);
       x = build2 (NE_EXPR, boolean_type_node, x,
 		  build_int_cst (TREE_TYPE (x), 0));
       x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
@@ -2688,12 +2689,12 @@  lower_reduction_clauses (tree clauses, g
 	}
     }
 
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
+  stmt = gimple_build_call (built_in_decls (BUILT_IN_GOMP_ATOMIC_START), 0);
   gimple_seq_add_stmt (stmt_seqp, stmt);
 
   gimple_seq_add_seq (stmt_seqp, sub_seq);
 
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
+  stmt = gimple_build_call (built_in_decls (BUILT_IN_GOMP_ATOMIC_END), 0);
   gimple_seq_add_stmt (stmt_seqp, stmt);
 }
 
@@ -2917,9 +2918,10 @@  expand_parallel_call (struct omp_region 
   tree t, t1, t2, val, cond, c, clauses;
   gimple_stmt_iterator gsi;
   gimple stmt;
-  int start_ix;
+  enum built_in_function start_ix;
   location_t clause_loc;
   VEC(tree,gc) *args;
+  int ix;
 
   clauses = gimple_omp_parallel_clauses (entry_stmt);
 
@@ -2932,10 +2934,10 @@  expand_parallel_call (struct omp_region 
 	{
 	case GIMPLE_OMP_FOR:
 	  gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
-	  start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
-		     + (region->inner->sched_kind
-			== OMP_CLAUSE_SCHEDULE_RUNTIME
-			? 3 : region->inner->sched_kind);
+	  ix = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
+		+ ((region->inner->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
+		   ? 3 : region->inner->sched_kind));
+	  start_ix = (enum built_in_function)ix;
 	  break;
 	case GIMPLE_OMP_SECTIONS:
 	  start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
@@ -3057,7 +3059,7 @@  expand_parallel_call (struct omp_region 
   VEC_splice (tree, args, ws_args);
 
   t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
-			       built_in_decls[start_ix], args);
+			       built_in_decls (start_ix), args);
 
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 			    false, GSI_CONTINUE_LINKING);
@@ -3073,7 +3075,7 @@  expand_parallel_call (struct omp_region 
 			    false, GSI_CONTINUE_LINKING);
 
   t = build_call_expr_loc (gimple_location (entry_stmt),
-			   built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
+			   built_in_decls (BUILT_IN_GOMP_PARALLEL_END), 0);
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 			    false, GSI_CONTINUE_LINKING);
 }
@@ -3125,7 +3127,7 @@  expand_task_call (basic_block bb, gimple
   else
     t3 = build_fold_addr_expr_loc (loc, t);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
+  t = build_call_expr (built_in_decls (BUILT_IN_GOMP_TASK), 7, t1, t2, t3,
 		       gimple_omp_task_arg_size (entry_stmt),
 		       gimple_omp_task_arg_align (entry_stmt), cond, flags);
 
@@ -3150,7 +3152,7 @@  maybe_catch_exception (gimple_seq body)
   if (lang_hooks.eh_protect_cleanup_actions != NULL)
     decl = lang_hooks.eh_protect_cleanup_actions ();
   else
-    decl = built_in_decls[BUILT_IN_TRAP];
+    decl = built_in_decls (BUILT_IN_TRAP);
 
   g = gimple_build_eh_must_not_throw (decl);
   g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
@@ -3298,9 +3300,9 @@  optimize_omp_library_calls (gimple entry
   basic_block bb;
   gimple_stmt_iterator gsi;
   tree thr_num_id
-    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
+    = DECL_ASSEMBLER_NAME (built_in_decls (BUILT_IN_OMP_GET_THREAD_NUM));
   tree num_thr_id
-    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
+    = DECL_ASSEMBLER_NAME (built_in_decls (BUILT_IN_OMP_GET_NUM_THREADS));
   bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
 		      && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
 					  OMP_CLAUSE_UNTIED) != NULL);
@@ -3325,10 +3327,10 @@  optimize_omp_library_calls (gimple entry
 		   during the execution of the task region.  */
 		if (untied_task)
 		  continue;
-		built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
+		built_in = built_in_decls (BUILT_IN_OMP_GET_THREAD_NUM);
 	      }
 	    else if (DECL_NAME (decl) == num_thr_id)
-	      built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
+	      built_in = built_in_decls (BUILT_IN_OMP_GET_NUM_THREADS);
 	    else
 	      continue;
 
@@ -3812,7 +3814,7 @@  expand_omp_for_generic (struct omp_regio
     {
       /* In a combined parallel loop, emit a call to
 	 GOMP_loop_foo_next.  */
-      t = build_call_expr (built_in_decls[next_fn], 2,
+      t = build_call_expr (built_in_decls (next_fn), 2,
 			   build_fold_addr_expr (istart0),
 			   build_fold_addr_expr (iend0));
     }
@@ -3848,11 +3850,11 @@  expand_omp_for_generic (struct omp_regio
 	  if (fd->chunk_size)
 	    {
 	      t = fold_convert (fd->iter_type, fd->chunk_size);
-	      t = build_call_expr (built_in_decls[start_fn], 6,
+	      t = build_call_expr (built_in_decls (start_fn), 6,
 				   t0, t1, t2, t, t3, t4);
 	    }
 	  else
-	    t = build_call_expr (built_in_decls[start_fn], 5,
+	    t = build_call_expr (built_in_decls (start_fn), 5,
 				 t0, t1, t2, t3, t4);
 	}
       else
@@ -3864,17 +3866,17 @@  expand_omp_for_generic (struct omp_regio
 	     argument, true for < loops and false for > loops.
 	     In Fortran, the C bool type can be different from
 	     boolean_type_node.  */
-	  c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn]));
+	  c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls (start_fn)));
 	  t5 = build_int_cst (c_bool_type,
 			      fd->loop.cond_code == LT_EXPR ? 1 : 0);
 	  if (fd->chunk_size)
 	    {
 	      t = fold_convert (fd->iter_type, fd->chunk_size);
-	      t = build_call_expr (built_in_decls[start_fn], 7,
+	      t = build_call_expr (built_in_decls (start_fn), 7,
 				   t5, t0, t1, t2, t, t3, t4);
 	    }
 	  else
-	    t = build_call_expr (built_in_decls[start_fn], 6,
+	    t = build_call_expr (built_in_decls (start_fn), 6,
 				 t5, t0, t1, t2, t3, t4);
 	}
     }
@@ -4031,7 +4033,7 @@  expand_omp_for_generic (struct omp_regio
       /* Emit code to get the next parallel iteration in L2_BB.  */
       gsi = gsi_start_bb (l2_bb);
 
-      t = build_call_expr (built_in_decls[next_fn], 2,
+      t = build_call_expr (built_in_decls (next_fn), 2,
 			   build_fold_addr_expr (istart0),
 			   build_fold_addr_expr (iend0));
       t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
@@ -4046,9 +4048,9 @@  expand_omp_for_generic (struct omp_regio
   /* Add the loop cleanup function.  */
   gsi = gsi_last_bb (exit_bb);
   if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
-    t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
+    t = built_in_decls (BUILT_IN_GOMP_LOOP_END_NOWAIT);
   else
-    t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
+    t = built_in_decls (BUILT_IN_GOMP_LOOP_END);
   stmt = gimple_build_call (t, 0);
   gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
@@ -4169,12 +4171,12 @@  expand_omp_for_static_nochunk (struct om
   gsi = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+  t = build_call_expr (built_in_decls (BUILT_IN_OMP_GET_NUM_THREADS), 0);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  t = build_call_expr (built_in_decls (BUILT_IN_OMP_GET_THREAD_NUM), 0);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
@@ -4391,12 +4393,12 @@  expand_omp_for_static_chunk (struct omp_
   si = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+  t = build_call_expr (built_in_decls (BUILT_IN_OMP_GET_NUM_THREADS), 0);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  t = build_call_expr (built_in_decls(BUILT_IN_OMP_GET_THREAD_NUM), 0);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
@@ -4778,13 +4780,13 @@  expand_omp_sections (struct omp_region *
 	 call GOMP_sections_start.  */
       t = build_int_cst (unsigned_type_node,
 			 exit_reachable ? len - 1 : len);
-      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
+      u = built_in_decls (BUILT_IN_GOMP_SECTIONS_START);
       stmt = gimple_build_call (u, 1, t);
     }
   else
     {
       /* Otherwise, call GOMP_sections_next.  */
-      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
+      u = built_in_decls (BUILT_IN_GOMP_SECTIONS_NEXT);
       stmt = gimple_build_call (u, 0);
     }
   gimple_call_set_lhs (stmt, vin);
@@ -4866,7 +4868,7 @@  expand_omp_sections (struct omp_region *
   VEC_free (tree, heap, label_vec);
 
   si = gsi_start_bb (default_bb);
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
+  stmt = gimple_build_call (built_in_decls (BUILT_IN_TRAP), 0);
   gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
 
   if (exit_reachable)
@@ -4875,7 +4877,7 @@  expand_omp_sections (struct omp_region *
       si = gsi_last_bb (l1_bb);
       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
 
-      stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
+      stmt = gimple_build_call (built_in_decls (BUILT_IN_GOMP_SECTIONS_NEXT), 0);
       gimple_call_set_lhs (stmt, vnext);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
@@ -4885,9 +4887,9 @@  expand_omp_sections (struct omp_region *
       /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
       si = gsi_last_bb (l2_bb);
       if (gimple_omp_return_nowait_p (gsi_stmt (si)))
-	t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
+	t = built_in_decls (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
       else
-	t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
+	t = built_in_decls (BUILT_IN_GOMP_SECTIONS_END);
       stmt = gimple_build_call (t, 0);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
@@ -5085,7 +5087,7 @@  expand_omp_atomic_fetch_op (basic_block 
   else
     return false;
 
-  decl = built_in_decls[(need_new ? newbase : oldbase) + index + 1];
+  decl = built_in_set_decl_add ((need_new ? newbase : oldbase), index + 1);
   if (decl == NULL_TREE)
     return false;
   itype = TREE_TYPE (TREE_TYPE (decl));
@@ -5167,7 +5169,8 @@  expand_omp_atomic_pipeline (basic_block 
   gimple phi, stmt;
   edge e;
 
-  cmpxchg = built_in_decls[BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N + index + 1];
+  cmpxchg = built_in_set_decl_add (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N,
+				   index + 1);
   if (cmpxchg == NULL_TREE)
     return false;
   type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
@@ -5355,7 +5358,7 @@  expand_omp_atomic_mutex (basic_block loa
   si = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
 
-  t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
+  t = built_in_decls (BUILT_IN_GOMP_ATOMIC_START);
   t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
@@ -5370,7 +5373,7 @@  expand_omp_atomic_mutex (basic_block loa
 			      stored_val);
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
 
-  t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
+  t = built_in_decls (BUILT_IN_GOMP_ATOMIC_END);
   t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&si, true);
@@ -5806,7 +5809,7 @@  lower_omp_single_simple (gimple single_s
   gimple call, cond;
   tree lhs, decl;
 
-  decl = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
+  decl = built_in_decls (BUILT_IN_GOMP_SINGLE_START);
   lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
   call = gimple_build_call (decl, 0);
   gimple_call_set_lhs (call, lhs);
@@ -5855,7 +5858,7 @@  lower_omp_single_simple (gimple single_s
 static void
 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
 {
-  tree ptr_type, t, l0, l1, l2;
+  tree ptr_type, t, l0, l1, l2, bfn;
   gimple_seq copyin_seq;
   location_t loc = gimple_location (single_stmt);
 
@@ -5868,7 +5871,8 @@  lower_omp_single_copy (gimple single_stm
   l1 = create_artificial_label (loc);
   l2 = create_artificial_label (loc);
 
-  t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
+  bfn = built_in_decls (BUILT_IN_GOMP_SINGLE_COPY_START);
+  t = build_call_expr_loc (loc, bfn, 0);
   t = fold_convert_loc (loc, ptr_type, t);
   gimplify_assign (ctx->receiver_decl, t, pre_p);
 
@@ -5887,8 +5891,8 @@  lower_omp_single_copy (gimple single_stm
 			      &copyin_seq, ctx);
 
   t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
-  t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END],
-		       1, t);
+  bfn = built_in_decls (BUILT_IN_GOMP_SINGLE_COPY_END);
+  t = build_call_expr_loc (loc, bfn, 1, t);
   gimplify_and_add (t, pre_p);
 
   t = build_and_jump (&l2);
@@ -5955,7 +5959,7 @@  lower_omp_single (gimple_stmt_iterator *
 static void
 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
-  tree block, lab = NULL, x;
+  tree block, lab = NULL, x, bfn;
   gimple stmt = gsi_stmt (*gsi_p), bind;
   location_t loc = gimple_location (stmt);
   gimple_seq tseq;
@@ -5967,7 +5971,8 @@  lower_omp_master (gimple_stmt_iterator *
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
       				 block);
 
-  x = build_call_expr_loc (loc, built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  bfn = built_in_decls (BUILT_IN_OMP_GET_THREAD_NUM);
+  x = build_call_expr_loc (loc, bfn, 0);
   x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
   x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
   tseq = NULL;
@@ -6006,7 +6011,7 @@  lower_omp_ordered (gimple_stmt_iterator 
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
       				   block);
 
-  x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
+  x = gimple_build_call (built_in_decls (BUILT_IN_GOMP_ORDERED_START), 0);
   gimple_bind_add_stmt (bind, x);
 
   lower_omp (gimple_omp_body (stmt), ctx);
@@ -6014,7 +6019,7 @@  lower_omp_ordered (gimple_stmt_iterator 
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
 
-  x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
+  x = gimple_build_call (built_in_decls (BUILT_IN_GOMP_ORDERED_END), 0);
   gimple_bind_add_stmt (bind, x);
 
   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
@@ -6080,19 +6085,19 @@  lower_omp_critical (gimple_stmt_iterator
       else
 	decl = (tree) n->value;
 
-      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
+      lock = built_in_decls (BUILT_IN_GOMP_CRITICAL_NAME_START);
       lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
 
-      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
+      unlock = built_in_decls (BUILT_IN_GOMP_CRITICAL_NAME_END);
       unlock = build_call_expr_loc (loc, unlock, 1,
 				build_fold_addr_expr_loc (loc, decl));
     }
   else
     {
-      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
+      lock = built_in_decls (BUILT_IN_GOMP_CRITICAL_START);
       lock = build_call_expr_loc (loc, lock, 0);
 
-      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
+      unlock = built_in_decls (BUILT_IN_GOMP_CRITICAL_END);
       unlock = build_call_expr_loc (loc, unlock, 0);
     }
 
Index: gcc/objc/objc-next-runtime-abi-01.c
===================================================================
--- gcc/objc/objc-next-runtime-abi-01.c	(.../trunk)	(revision 179369)
+++ gcc/objc/objc-next-runtime-abi-01.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2919,7 +2919,7 @@  objc_build_exc_ptr (struct objc_try_cont
   else
     {
       tree t;
-      t = built_in_decls[BUILT_IN_EH_POINTER];
+      t = built_in_decls (BUILT_IN_EH_POINTER);
       t = build_call_expr (t, 1, integer_zero_node);
       return fold_convert (objc_object_type, t);
     }
Index: gcc/objc/objc-next-runtime-abi-02.c
===================================================================
--- gcc/objc/objc-next-runtime-abi-02.c	(.../trunk)	(revision 179369)
+++ gcc/objc/objc-next-runtime-abi-02.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -3676,7 +3676,7 @@  static tree
 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
 {
   tree t;
-  t = built_in_decls[BUILT_IN_EH_POINTER];
+  t = built_in_decls (BUILT_IN_EH_POINTER);
   t = build_call_expr (t, 1, integer_zero_node);
   return fold_convert (objc_object_type, t);
 }
Index: gcc/objc/objc-gnu-runtime-abi-01.c
===================================================================
--- gcc/objc/objc-gnu-runtime-abi-01.c	(.../trunk)	(revision 179369)
+++ gcc/objc/objc-gnu-runtime-abi-01.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2226,7 +2226,7 @@  static tree
 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
 {
   tree t;
-  t = built_in_decls[BUILT_IN_EH_POINTER];
+  t = built_in_decls (BUILT_IN_EH_POINTER);
   t = build_call_expr (t, 1, integer_zero_node);
   return fold_convert (objc_object_type, t);
 }
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(.../trunk)	(revision 179369)
+++ gcc/cp/decl.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1187,7 +1187,7 @@  duplicate_decls (tree newdecl, tree oldd
   unsigned olddecl_uid = DECL_UID (olddecl);
   int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
   int new_defines_function = 0;
-  tree new_template_info;
+  tree new_template_info, bfn;
 
   if (newdecl == olddecl)
     return olddecl;
@@ -1358,10 +1358,10 @@  duplicate_decls (tree newdecl, tree oldd
 	  && DECL_ANTICIPATED (olddecl)
 	  && TREE_NOTHROW (newdecl)
 	  && !TREE_NOTHROW (olddecl)
-	  && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
-	  && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
+	  && (bfn = built_in_decls (DECL_FUNCTION_CODE (olddecl))) != NULL_TREE
+	  && bfn != olddecl
 	  && types_match)
-	TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+	TREE_NOTHROW (bfn) = 1;
 
       /* Whether or not the builtin can throw exceptions has no
 	 bearing on this declarator.  */
@@ -2136,17 +2136,20 @@  duplicate_decls (tree newdecl, tree oldd
 		 regardless of declaration matches.  */
 	      COPY_DECL_RTL (olddecl, newdecl);
 	      if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
-		switch (DECL_FUNCTION_CODE (newdecl))
-		  {
-		    /* If a compatible prototype of these builtin functions
-		       is seen, assume the runtime implements it with the
-		       expected semantics.  */
-		  case BUILT_IN_STPCPY:
-		    implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
-		      = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
-		  default:
-		    break;
-		  }
+		{
+		  enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+		  switch (fncode)
+		    {
+		      /* If a compatible prototype of these builtin functions
+			 is seen, assume the runtime implements it with the
+			 expected semantics.  */
+		    case BUILT_IN_STPCPY:
+		      built_in_set_implicit (fncode, built_in_decls (fncode));
+		      break;
+		    default:
+		      break;
+		    }
+		}
 	    }
 
 	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c	(.../trunk)	(revision 179369)
+++ gcc/cp/except.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -140,7 +140,7 @@  build_eh_type_type (tree type)
 tree
 build_exc_ptr (void)
 {
-  return build_call_n (built_in_decls [BUILT_IN_EH_POINTER],
+  return build_call_n (built_in_decls (BUILT_IN_EH_POINTER),
 		       1, integer_zero_node);
 }
 
@@ -333,7 +333,7 @@  choose_personality_routine (enum languag
 
     case lang_java:
       state = chose_java;
-      terminate_node = built_in_decls [BUILT_IN_ABORT];
+      terminate_node = built_in_decls (BUILT_IN_ABORT);
       pragma_java_exceptions = true;
       break;
 
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(.../trunk)	(revision 179369)
+++ gcc/cp/semantics.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -4797,7 +4797,7 @@  finish_omp_atomic (enum tree_code code, 
 void
 finish_omp_barrier (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
+  tree fn = built_in_decls (BUILT_IN_GOMP_BARRIER);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4807,7 +4807,7 @@  finish_omp_barrier (void)
 void
 finish_omp_flush (void)
 {
-  tree fn = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+  tree fn = built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4817,7 +4817,7 @@  finish_omp_flush (void)
 void
 finish_omp_taskwait (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+  tree fn = built_in_decls (BUILT_IN_GOMP_TASKWAIT);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4827,7 +4827,7 @@  finish_omp_taskwait (void)
 void
 finish_omp_taskyield (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  tree fn = built_in_decls (BUILT_IN_GOMP_TASKYIELD);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c	(.../trunk)	(revision 179369)
+++ gcc/tree-ssa-ccp.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2172,7 +2172,7 @@  optimize_stdarg_builtin (gimple call)
     case BUILT_IN_VA_START:
       if (!va_list_simple_ptr
 	  || targetm.expand_builtin_va_start != NULL
-          || built_in_decls[BUILT_IN_NEXT_ARG] == NULL)
+          || built_in_decls (BUILT_IN_NEXT_ARG) == NULL)
 	return NULL_TREE;
 
       if (gimple_call_num_args (call) != 2)
@@ -2185,7 +2185,7 @@  optimize_stdarg_builtin (gimple call)
 	return NULL_TREE;
 
       lhs = build_fold_indirect_ref_loc (loc, lhs);
-      rhs = build_call_expr_loc (loc, built_in_decls[BUILT_IN_NEXT_ARG],
+      rhs = build_call_expr_loc (loc, built_in_decls (BUILT_IN_NEXT_ARG),
                              1, integer_zero_node);
       rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
       return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(.../trunk)	(revision 179369)
+++ gcc/builtins.def	(.../branches/ibm/builtin)	(revision 179396)
@@ -173,6 +173,9 @@  along with GCC; see the file COPYING3.  
 #undef ATTR_MATHFN_FPROUNDING_STORE
 #define ATTR_MATHFN_FPROUNDING_STORE ATTR_NOTHROW_LEAF_LIST
 
+/* Make sure 0 is not a legitimate builtin index.  */
+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)
Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c	(.../trunk)	(revision 179369)
+++ gcc/tree-ssa-math-opts.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1805,9 +1805,9 @@  execute_optimize_bswap (void)
   if (sizeof (HOST_WIDEST_INT) < 8)
     return 0;
 
-  bswap32_p = (built_in_decls[BUILT_IN_BSWAP32]
+  bswap32_p = (built_in_decls (BUILT_IN_BSWAP32)
 	       && optab_handler (bswap_optab, SImode) != CODE_FOR_nothing);
-  bswap64_p = (built_in_decls[BUILT_IN_BSWAP64]
+  bswap64_p = (built_in_decls (BUILT_IN_BSWAP64)
 	       && (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing
 		   || (bswap32_p && word_mode == SImode)));
 
@@ -1818,13 +1818,13 @@  execute_optimize_bswap (void)
      assumes that the return and argument type are the same.  */
   if (bswap32_p)
     {
-      tree fndecl = built_in_decls[BUILT_IN_BSWAP32];
+      tree fndecl = built_in_decls (BUILT_IN_BSWAP32);
       bswap32_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
   if (bswap64_p)
     {
-      tree fndecl = built_in_decls[BUILT_IN_BSWAP64];
+      tree fndecl = built_in_decls (BUILT_IN_BSWAP64);
       bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
@@ -1858,14 +1858,14 @@  execute_optimize_bswap (void)
 	    case 32:
 	      if (bswap32_p)
 		{
-		  fndecl = built_in_decls[BUILT_IN_BSWAP32];
+		  fndecl = built_in_decls (BUILT_IN_BSWAP32);
 		  bswap_type = bswap32_type;
 		}
 	      break;
 	    case 64:
 	      if (bswap64_p)
 		{
-		  fndecl = built_in_decls[BUILT_IN_BSWAP64];
+		  fndecl = built_in_decls (BUILT_IN_BSWAP64);
 		  bswap_type = bswap64_type;
 		}
 	      break;
Index: gcc/gimple-low.c
===================================================================
--- gcc/gimple-low.c	(.../trunk)	(revision 179369)
+++ gcc/gimple-low.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -169,7 +169,7 @@  lower_function_body (void)
 	 and insert.  */
       disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
       arg = build_addr (disp_label, current_function_decl);
-      t = implicit_built_in_decls[BUILT_IN_SETJMP_DISPATCHER];
+      t = implicit_built_in_decls (BUILT_IN_SETJMP_DISPATCHER);
       x = gimple_build_call (t, 1, arg);
       gimple_call_set_lhs (x, disp_var);
 
@@ -861,7 +861,7 @@  lower_builtin_setjmp (gimple_stmt_iterat
 
   /* Build '__builtin_setjmp_setup (BUF, NEXT_LABEL)' and insert.  */
   arg = build_addr (next_label, current_function_decl);
-  t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP];
+  t = implicit_built_in_decls (BUILT_IN_SETJMP_SETUP);
   g = gimple_build_call (t, 2, gimple_call_arg (stmt, 0), arg);
   gimple_set_location (g, loc);
   gimple_set_block (g, gimple_block (stmt));
@@ -886,7 +886,7 @@  lower_builtin_setjmp (gimple_stmt_iterat
 
   /* Build '__builtin_setjmp_receiver (NEXT_LABEL)' and insert.  */
   arg = build_addr (next_label, current_function_decl);
-  t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER];
+  t = implicit_built_in_decls (BUILT_IN_SETJMP_RECEIVER);
   g = gimple_build_call (t, 1, arg);
   gimple_set_location (g, loc);
   gimple_set_block (g, gimple_block (stmt));
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(.../trunk)	(revision 179369)
+++ gcc/go/gofrontend/gogo-tree.cc	(.../branches/ibm/builtin)	(revision 179396)
@@ -69,8 +69,7 @@  define_builtin(built_in_function bcode, 
 				   libname, NULL_TREE);
   if (const_p)
     TREE_READONLY(decl) = 1;
-  built_in_decls[bcode] = decl;
-  implicit_built_in_decls[bcode] = decl;
+  built_in_set_decl (bcode, decl, decl);
   builtin_functions[name] = decl;
   if (libname != NULL)
     {
@@ -2311,13 +2310,13 @@  Gogo::make_trampoline(tree fnaddr, tree 
   x = save_expr(x);
 
   // Initialize the trampoline.
-  tree ini = build_call_expr(implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE],
+  tree ini = build_call_expr(implicit_built_in_decls(BUILT_IN_INIT_TRAMPOLINE),
 			     3, x, fnaddr, closure);
 
   // On some targets the trampoline address needs to be adjusted.  For
   // example, when compiling in Thumb mode on the ARM, the address
   // needs to have the low bit set.
-  x = build_call_expr(implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE],
+  x = build_call_expr(implicit_built_in_decls(BUILT_IN_ADJUST_TRAMPOLINE),
 		      1, x);
   x = fold_convert(TREE_TYPE(fnaddr), x);
 
Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c	(.../trunk)	(revision 179369)
+++ gcc/ada/gcc-interface/utils.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -5629,7 +5629,7 @@  def_builtin_1 (enum built_in_function fn
 
   /* Preserve an already installed decl.  It most likely was setup in advance
      (e.g. as part of the internal builtins) for specific reasons.  */
-  if (built_in_decls[(int) fncode] != NULL_TREE)
+  if (built_in_decls (fncode) != NULL_TREE)
     return;
 
   gcc_assert ((!both_p && !fallback_p)
@@ -5646,9 +5646,7 @@  def_builtin_1 (enum built_in_function fn
     add_builtin_function (libname, libtype, fncode, fnclass,
 			  NULL, fnattrs);
 
-  built_in_decls[(int) fncode] = decl;
-  if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
+  built_in_set_decl (fncode, decl, implicit_p ? decl : NULL_TREE);
 }
 
 static int flag_isoc94 = 0;
Index: gcc/ada/gcc-interface/trans.c
===================================================================
--- gcc/ada/gcc-interface/trans.c	(.../trunk)	(revision 179369)
+++ gcc/ada/gcc-interface/trans.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -3899,7 +3899,7 @@  Exception_Handler_to_gnu_zcx (Node_Id gn
      time, and reuse it to feed the end_handler hook's argument at exit.  */
 
   gnu_current_exc_ptr
-    = build_call_expr (built_in_decls [BUILT_IN_EH_POINTER],
+    = build_call_expr (built_in_decls (BUILT_IN_EH_POINTER),
 		       1, integer_zero_node);
   prev_gnu_incoming_exc_ptr = gnu_incoming_exc_ptr;
   gnu_incoming_exc_ptr = create_var_decl (get_identifier ("EXPTR"), NULL_TREE,
@@ -5189,7 +5189,7 @@  gnat_to_gnu (Node_Id gnat_node)
 	      to_ptr = build_fold_addr_expr (to);
 	      from_ptr = build_fold_addr_expr (from);
 
-	      t = implicit_built_in_decls[BUILT_IN_MEMMOVE];
+	      t = implicit_built_in_decls (BUILT_IN_MEMMOVE);
 	      gnu_result = build_call_expr (t, 3, to_ptr, from_ptr, size);
 	   }
 	}
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(.../trunk)	(revision 179369)
+++ gcc/c-decl.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2372,16 +2372,19 @@  merge_decls (tree newdecl, tree olddecl,
 	    {
 	      C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
 	      if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
-		switch (DECL_FUNCTION_CODE (newdecl))
-		  {
-		  /* If a compatible prototype of these builtin functions
-		     is seen, assume the runtime implements it with the
-		     expected semantics.  */
-		  case BUILT_IN_STPCPY:
-		    implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
-		      = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
-		  default:
-		    break;
+		{
+		  enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+		  switch (fncode)
+		    {
+		      /* If a compatible prototype of these builtin functions
+			 is seen, assume the runtime implements it with the
+			 expected semantics.  */
+		    case BUILT_IN_STPCPY:
+		      built_in_set_implicit (fncode, built_in_decls (fncode));
+		      break;
+		    default:
+		      break;
+		    }
 		  }
 	    }
 	  else
@@ -4338,7 +4341,7 @@  finish_decl (tree decl, location_t init_
     }
 
   /* If this is a function and an assembler name is specified, reset DECL_RTL
-     so we can give it its new name.  Also, update built_in_decls if it
+     so we can give it its new name.  Also, update built_in_decl_info if it
      was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c	(.../trunk)	(revision 179369)
+++ gcc/tree-eh.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2934,7 +2934,7 @@  lower_resx (basic_block bb, gimple stmt,
 
 	 Resolve this by expanding the resx node to an abort.  */
 
-      fn = implicit_built_in_decls[BUILT_IN_TRAP];
+      fn = implicit_built_in_decls (BUILT_IN_TRAP);
       x = gimple_build_call (fn, 0);
       gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 
@@ -2991,7 +2991,7 @@  lower_resx (basic_block bb, gimple stmt,
 	  edge_iterator ei;
 	  tree dst_nr = build_int_cst (integer_type_node, dst_r->index);
 
-	  fn = implicit_built_in_decls[BUILT_IN_EH_COPY_VALUES];
+	  fn = implicit_built_in_decls (BUILT_IN_EH_COPY_VALUES);
 	  src_nr = build_int_cst (integer_type_node, src_r->index);
 	  x = gimple_build_call (fn, 2, dst_nr, src_nr);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
@@ -3026,13 +3026,13 @@  lower_resx (basic_block bb, gimple stmt,
 	 with no arguments for C++ and Java.  Check for that.  */
       if (src_r->use_cxa_end_cleanup)
 	{
-	  fn = implicit_built_in_decls[BUILT_IN_CXA_END_CLEANUP];
+	  fn = implicit_built_in_decls (BUILT_IN_CXA_END_CLEANUP);
 	  x = gimple_build_call (fn, 0);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 	}
       else
 	{
-	  fn = implicit_built_in_decls[BUILT_IN_EH_POINTER];
+	  fn = implicit_built_in_decls (BUILT_IN_EH_POINTER);
 	  src_nr = build_int_cst (integer_type_node, src_r->index);
 	  x = gimple_build_call (fn, 1, src_nr);
 	  var = create_tmp_var (ptr_type_node, NULL);
@@ -3040,7 +3040,7 @@  lower_resx (basic_block bb, gimple stmt,
 	  gimple_call_set_lhs (x, var);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 
-	  fn = implicit_built_in_decls[BUILT_IN_UNWIND_RESUME];
+	  fn = implicit_built_in_decls (BUILT_IN_UNWIND_RESUME);
 	  x = gimple_build_call (fn, 1, var);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 	}
@@ -3206,7 +3206,7 @@  lower_eh_dispatch (basic_block src, gimp
 	  }
 	else
 	  {
-	    fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
+	    fn = implicit_built_in_decls (BUILT_IN_EH_FILTER);
 	    x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
 							 region_nr));
 	    filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
@@ -3232,7 +3232,7 @@  lower_eh_dispatch (basic_block src, gimp
 	edge b_e = BRANCH_EDGE (src);
 	edge f_e = FALLTHRU_EDGE (src);
 
-	fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
+	fn = implicit_built_in_decls (BUILT_IN_EH_FILTER);
 	x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
 						     region_nr));
 	filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans-expr.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1124,22 +1124,22 @@  gfc_conv_power_op (gfc_se * se, gfc_expr
 	      switch (kind)
 		{
 		case 0:
-		  fndecl = built_in_decls[BUILT_IN_POWIF];
+		  fndecl = built_in_decls (BUILT_IN_POWIF);
 		  break;
 		
 		case 1:
-		  fndecl = built_in_decls[BUILT_IN_POWI];
+		  fndecl = built_in_decls (BUILT_IN_POWI);
 		  break;
 
 		case 2:
-		  fndecl = built_in_decls[BUILT_IN_POWIL];
+		  fndecl = built_in_decls (BUILT_IN_POWIL);
 		  break;
 
 		case 3:
 		  /* Use the __builtin_powil() only if real(kind=16) is 
 		     actually the C long double type.  */
 		  if (!gfc_real16_is_float128)
-		    fndecl = built_in_decls[BUILT_IN_POWIL];
+		    fndecl = built_in_decls (BUILT_IN_POWIL);
 		  break;
 
 		default:
@@ -3855,7 +3855,7 @@  fill_with_spaces (tree start, tree type,
   /* For a simple char type, we can call memset().  */
   if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
     return build_call_expr_loc (input_location,
-			    built_in_decls[BUILT_IN_MEMSET], 3, start,
+			    built_in_decls (BUILT_IN_MEMSET), 3, start,
 			    build_int_cst (gfc_get_int_type (gfc_c_int_kind),
 					   lang_hooks.to_target_charset (' ')),
 			    size);
@@ -4015,12 +4015,12 @@  gfc_trans_string_copy (stmtblock_t * blo
   cond2 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, slen,
 			   dlen);
   tmp2 = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMMOVE],
+			  built_in_decls (BUILT_IN_MEMMOVE),
 			  3, dest, src, dlen);
 
   /* Else copy and pad with spaces.  */
   tmp3 = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMMOVE],
+			  built_in_decls (BUILT_IN_MEMMOVE),
 			  3, dest, src, slen);
 
   tmp4 = fold_build_pointer_plus_loc (input_location, dest, slen);
@@ -5816,7 +5816,7 @@  gfc_trans_zero_assign (gfc_expr * expr)
 
   /* Construct call to __builtin_memset.  */
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_MEMSET],
+			 built_in_decls (BUILT_IN_MEMSET),
 			 3, dest, integer_zero_node, len);
   return fold_convert (void_type_node, tmp);
 }
@@ -5845,7 +5845,7 @@  gfc_build_memcpy_call (tree dst, tree sr
 
   /* Construct call to __builtin_memcpy.  */
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_MEMCPY], 3, dst, src, len);
+			 built_in_decls (BUILT_IN_MEMCPY), 3, dst, src, len);
   return fold_convert (void_type_node, tmp);
 }
 
@@ -6056,7 +6056,7 @@  alloc_scalar_allocatable_for_assignment 
     }
 
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MALLOC], 1,
+			     built_in_decls (BUILT_IN_MALLOC), 1,
 			     size_in_bytes);
   tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
   gfc_add_modify (block, lse.expr, tmp);
@@ -6083,7 +6083,7 @@  alloc_scalar_allocatable_for_assignment 
 		      build_empty_stmt (input_location));
       gfc_add_expr_to_block (block, tmp);
       tmp = build_call_expr_loc (input_location,
-				 built_in_decls[BUILT_IN_REALLOC], 2,
+				 built_in_decls (BUILT_IN_REALLOC), 2,
 				 fold_convert (pvoid_type_node, lse.expr),
 				 size_in_bytes);
       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans-array.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1470,8 +1470,8 @@  gfc_trans_array_constructor_value (stmtb
 	      size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
 	      bound = build_int_cst (size_type_node, n * size);
 	      tmp = build_call_expr_loc (input_location,
-				     built_in_decls[BUILT_IN_MEMCPY], 3,
-				     tmp, init, bound);
+					 built_in_decls (BUILT_IN_MEMCPY), 3,
+					 tmp, init, bound);
 	      gfc_add_expr_to_block (&body, tmp);
 
 	      *poffset = fold_build2_loc (input_location, PLUS_EXPR,
@@ -6632,7 +6632,7 @@  duplicate_allocatable (tree dest, tree s
 	  gfc_add_expr_to_block (&block, tmp);
 	}
 
-      tmp = built_in_decls[BUILT_IN_MEMCPY];
+      tmp = built_in_decls (BUILT_IN_MEMCPY);
       tmp = build_call_expr_loc (input_location, tmp, 3,
 				 dest, src, size);
     }
@@ -6656,7 +6656,7 @@  duplicate_allocatable (tree dest, tree s
 
       /* We know the temporary and the value will be the same length,
 	 so can use memcpy.  */
-      tmp = built_in_decls[BUILT_IN_MEMCPY];
+      tmp = built_in_decls (BUILT_IN_MEMCPY);
       tmp = build_call_expr_loc (input_location,
 			tmp, 3, gfc_conv_descriptor_data_get (dest),
 			gfc_conv_descriptor_data_get (src), size);
@@ -7412,7 +7412,7 @@  gfc_alloc_allocatable_for_assignment (gf
      in the array reference - (*desc.data)[<element>]. */
   gfc_init_block (&realloc_block);
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_REALLOC], 2,
+			     built_in_decls (BUILT_IN_REALLOC), 2,
 			     fold_convert (pvoid_type_node, array1),
 			     size2);
   gfc_conv_descriptor_data_set (&realloc_block,
@@ -7428,7 +7428,7 @@  gfc_alloc_allocatable_for_assignment (gf
   /* Malloc expression.  */
   gfc_init_block (&alloc_block);
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MALLOC], 1,
+			     built_in_decls (BUILT_IN_MALLOC), 1,
 			     size2);
   gfc_conv_descriptor_data_set (&alloc_block,
 				desc, tmp);
Index: gcc/fortran/trans-openmp.c
===================================================================
--- gcc/fortran/trans-openmp.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans-openmp.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -249,7 +249,7 @@  gfc_omp_clause_copy_ctor (tree clause, t
   gfc_conv_descriptor_data_set (&cond_block, dest, ptr);
 
   call = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMCPY], 3, ptr,
+			  built_in_decls (BUILT_IN_MEMCPY), 3, ptr,
 			  fold_convert (pvoid_type_node,
 					gfc_conv_descriptor_data_get (src)),
 			  size);
@@ -300,7 +300,7 @@  gfc_omp_clause_assign_op (tree clause AT
 			  size, esize);
   size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
   call = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMCPY], 3,
+			  built_in_decls (BUILT_IN_MEMCPY), 3,
 			  fold_convert (pvoid_type_node,
 					gfc_conv_descriptor_data_get (dest)),
 			  fold_convert (pvoid_type_node,
@@ -1273,7 +1273,7 @@  gfc_trans_omp_atomic (gfc_code *code)
 static tree
 gfc_trans_omp_barrier (void)
 {
-  tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
+  tree decl = built_in_decls (BUILT_IN_GOMP_BARRIER);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
@@ -1547,7 +1547,7 @@  gfc_trans_omp_do (gfc_code *code, stmtbl
 static tree
 gfc_trans_omp_flush (void)
 {
-  tree decl = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+  tree decl = built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
@@ -1738,14 +1738,14 @@  gfc_trans_omp_task (gfc_code *code)
 static tree
 gfc_trans_omp_taskwait (void)
 {
-  tree decl = built_in_decls [BUILT_IN_GOMP_TASKWAIT];
+  tree decl = built_in_decls (BUILT_IN_GOMP_TASKWAIT);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
 static tree
 gfc_trans_omp_taskyield (void)
 {
-  tree decl = built_in_decls [BUILT_IN_GOMP_TASKYIELD];
+  tree decl = built_in_decls (BUILT_IN_GOMP_TASKYIELD);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans-stmt.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -602,7 +602,7 @@  gfc_trans_stop (gfc_code *code, bool err
   if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
     {
       /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY.  */
-      tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+      tmp = built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE);
       tmp = build_call_expr_loc (input_location, tmp, 0);
       gfc_add_expr_to_block (&se.pre, tmp);
 
@@ -774,7 +774,7 @@  gfc_trans_sync (gfc_code *code, gfc_exec
       image control statements SYNC IMAGES and SYNC ALL.  */
    if (gfc_option.coarray == GFC_FCOARRAY_LIB)
      {
-	tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+	tmp = built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE);
 	tmp = build_call_expr_loc (input_location, tmp, 0);
 	gfc_add_expr_to_block (&se.pre, tmp);
      }
@@ -5076,7 +5076,7 @@  gfc_trans_allocate (gfc_code * code)
 			      slen);
 
       dlen = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_MEMCPY], 3,
+			      built_in_decls (BUILT_IN_MEMCPY), 3,
 		gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
 
       tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
@@ -5251,7 +5251,7 @@  gfc_trans_deallocate (gfc_code *code)
 			      slen);
 
       dlen = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_MEMCPY], 3,
+			      built_in_decls (BUILT_IN_MEMCPY), 3,
 		gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
 
       tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, astat,
Index: gcc/fortran/trans.c
===================================================================
--- gcc/fortran/trans.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -532,7 +532,7 @@  gfc_call_malloc (stmtblock_t * block, tr
   gfc_add_modify (&block2, res,
 		  fold_convert (prvoid_type_node,
 				build_call_expr_loc (input_location,
-				   built_in_decls[BUILT_IN_MALLOC], 1, size)));
+						     built_in_decls (BUILT_IN_MALLOC), 1, size)));
 
   /* Optionally check whether malloc was successful.  */
   if (gfc_option.rtcheck & GFC_RTCHECK_MEM)
@@ -604,7 +604,7 @@  gfc_allocate_using_malloc (stmtblock_t *
   gfc_add_modify (block, pointer,
 	  fold_convert (TREE_TYPE (pointer),
 		build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MALLOC], 1,
+			     built_in_decls (BUILT_IN_MALLOC), 1,
 			     fold_build2_loc (input_location,
 				      MAX_EXPR, size_type_node, size,
 				      build_int_cst (size_type_node, 1)))));
@@ -783,7 +783,7 @@  gfc_call_free (tree var)
   cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, var,
 			  build_int_cst (pvoid_type_node, 0));
   call = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_FREE], 1, var);
+			      built_in_decls (BUILT_IN_FREE), 1, var);
   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, call,
 			 build_empty_stmt (input_location));
   gfc_add_expr_to_block (&block, tmp);
@@ -871,7 +871,7 @@  gfc_deallocate_with_status (tree pointer
   /* When POINTER is not NULL, we free it.  */
   gfc_start_block (&non_null);
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_FREE], 1,
+			 built_in_decls (BUILT_IN_FREE), 1,
 			 fold_convert (pvoid_type_node, pointer));
   gfc_add_expr_to_block (&non_null, tmp);
 
@@ -968,7 +968,7 @@  gfc_deallocate_scalar_with_status (tree 
     }
   
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_FREE], 1,
+			 built_in_decls (BUILT_IN_FREE), 1,
 			 fold_convert (pvoid_type_node, pointer));
   gfc_add_expr_to_block (&non_null, tmp);
 
@@ -1026,7 +1026,7 @@  gfc_call_realloc (stmtblock_t * block, t
 
   /* Call realloc and check the result.  */
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_REALLOC], 2,
+			 built_in_decls (BUILT_IN_REALLOC), 2,
 			 fold_convert (pvoid_type_node, mem), size);
   gfc_add_modify (block, res, fold_convert (type, tmp));
   null_result = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
@@ -1593,7 +1593,7 @@  gfc_unlikely (tree cond)
   cond = fold_convert (long_integer_type_node, cond);
   tmp = build_zero_cst (long_integer_type_node);
   cond = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
+			      built_in_decls (BUILT_IN_EXPECT), 2, cond, tmp);
   cond = fold_convert (boolean_type_node, cond);
   return cond;
 }
@@ -1609,7 +1609,7 @@  gfc_likely (tree cond)
   cond = fold_convert (long_integer_type_node, cond);
   tmp = build_one_cst (long_integer_type_node);
   cond = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
+			      built_in_decls (BUILT_IN_EXPECT), 2, cond, tmp);
   cond = fold_convert (boolean_type_node, cond);
   return cond;
 }
Index: gcc/fortran/f95-lang.c
===================================================================
--- gcc/fortran/f95-lang.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/f95-lang.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -653,8 +653,8 @@  gfc_define_builtin (const char *name, tr
     DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
 					NULL, DECL_ATTRIBUTES (decl));
 
-  built_in_decls[code] = decl;
-  implicit_built_in_decls[code] = decl;
+  built_in_set_decl ((enum built_in_function)code, decl);
+  built_in_set_implicit ((enum built_in_function)code, decl);
 }
 
 
@@ -1005,7 +1005,7 @@  gfc_init_builtin_functions (void)
                                     size_type_node, NULL_TREE);
   gfc_define_builtin ("__builtin_malloc", ftype, BUILT_IN_MALLOC,
 		      "malloc", ATTR_NOTHROW_LEAF_LIST);
-  DECL_IS_MALLOC (built_in_decls[BUILT_IN_MALLOC]) = 1;
+  DECL_IS_MALLOC (built_in_decls (BUILT_IN_MALLOC)) = 1;
 
   ftype = build_function_type_list (pvoid_type_node,
                                     size_type_node, pvoid_type_node,
@@ -1121,7 +1121,7 @@  gfc_init_builtin_functions (void)
 
   gfc_define_builtin ("__builtin_trap", builtin_types[BT_FN_VOID],
 		      BUILT_IN_TRAP, NULL, ATTR_NOTHROW_LEAF_LIST);
-  TREE_THIS_VOLATILE (built_in_decls[BUILT_IN_TRAP]) = 1;
+  TREE_THIS_VOLATILE (built_in_decls (BUILT_IN_TRAP)) = 1;
 
   gfc_define_builtin ("__emutls_get_address",
 		      builtin_types[BT_FN_PTR_PTR],
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans-decl.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -4986,7 +4986,7 @@  create_main_function (tree fndecl)
     { 
       /* Per F2008, 8.5.1 END of the main program implies a
 	 SYNC MEMORY.  */ 
-      tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+      tmp = built_in_decls (BUILT_IN_SYNC_SYNCHRONIZE);
       tmp = build_call_expr_loc (input_location, tmp, 0);
       gfc_add_expr_to_block (&body, tmp);
 
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c	(.../trunk)	(revision 179369)
+++ gcc/fortran/trans-intrinsic.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -139,7 +139,7 @@  static tree
 builtin_decl_for_precision (enum built_in_function base_built_in,
 			    int precision)
 {
-  int i = END_BUILTINS;
+  enum built_in_function i = END_BUILTINS;
 
   gfc_intrinsic_map_t *m;
   for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
@@ -158,7 +158,7 @@  builtin_decl_for_precision (enum built_i
       return m->real16_decl;
     }
 
-  return (i == END_BUILTINS ? NULL_TREE : built_in_decls[i]);
+  return (i == END_BUILTINS ? NULL_TREE : built_in_decls (i));
 }
 
 
@@ -679,26 +679,26 @@  gfc_build_intrinsic_lib_fndecls (void)
        m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
     {
       if (m->float_built_in != END_BUILTINS)
-	m->real4_decl = built_in_decls[m->float_built_in];
+	m->real4_decl = built_in_decls (m->float_built_in);
       if (m->complex_float_built_in != END_BUILTINS)
-	m->complex4_decl = built_in_decls[m->complex_float_built_in];
+	m->complex4_decl = built_in_decls (m->complex_float_built_in);
       if (m->double_built_in != END_BUILTINS)
-	m->real8_decl = built_in_decls[m->double_built_in];
+	m->real8_decl = built_in_decls (m->double_built_in);
       if (m->complex_double_built_in != END_BUILTINS)
-	m->complex8_decl = built_in_decls[m->complex_double_built_in];
+	m->complex8_decl = built_in_decls (m->complex_double_built_in);
 
       /* If real(kind=10) exists, it is always long double.  */
       if (m->long_double_built_in != END_BUILTINS)
-	m->real10_decl = built_in_decls[m->long_double_built_in];
+	m->real10_decl = built_in_decls (m->long_double_built_in);
       if (m->complex_long_double_built_in != END_BUILTINS)
-	m->complex10_decl = built_in_decls[m->complex_long_double_built_in];
+	m->complex10_decl = built_in_decls (m->complex_long_double_built_in);
 
       if (!gfc_real16_is_float128)
 	{
 	  if (m->long_double_built_in != END_BUILTINS)
-	    m->real16_decl = built_in_decls[m->long_double_built_in];
+	    m->real16_decl = built_in_decls (m->long_double_built_in);
 	  if (m->complex_long_double_built_in != END_BUILTINS)
-	    m->complex16_decl = built_in_decls[m->complex_long_double_built_in];
+	    m->complex16_decl = built_in_decls (m->complex_long_double_built_in);
 	}
       else if (quad_decls[m->double_built_in] != NULL_TREE)
         {
@@ -2202,7 +2202,7 @@  gfc_conv_intrinsic_minmax (gfc_se * se, 
       if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
 	{
 	  isnan = build_call_expr_loc (input_location,
-				   built_in_decls[BUILT_IN_ISNAN], 1, mvar);
+				   built_in_decls (BUILT_IN_ISNAN), 1, mvar);
 	  tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
 				 boolean_type_node, tmp,
 				 fold_convert (boolean_type_node, isnan));
@@ -4079,17 +4079,17 @@  gfc_conv_intrinsic_leadz (gfc_se * se, g
   if (argsize <= INT_TYPE_SIZE)
     {
       arg_type = unsigned_type_node;
-      func = built_in_decls[BUILT_IN_CLZ];
+      func = built_in_decls (BUILT_IN_CLZ);
     }
   else if (argsize <= LONG_TYPE_SIZE)
     {
       arg_type = long_unsigned_type_node;
-      func = built_in_decls[BUILT_IN_CLZL];
+      func = built_in_decls (BUILT_IN_CLZL);
     }
   else if (argsize <= LONG_LONG_TYPE_SIZE)
     {
       arg_type = long_long_unsigned_type_node;
-      func = built_in_decls[BUILT_IN_CLZLL];
+      func = built_in_decls (BUILT_IN_CLZLL);
     }
   else
     {
@@ -4148,13 +4148,13 @@  gfc_conv_intrinsic_leadz (gfc_se * se, g
       tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
       tmp1 = fold_convert (result_type,
 			   build_call_expr_loc (input_location,	
-						built_in_decls[BUILT_IN_CLZLL],
+						built_in_decls (BUILT_IN_CLZLL),
 						1, tmp1));
 
       tmp2 = fold_convert (long_long_unsigned_type_node, arg);
       tmp2 = fold_convert (result_type,
 			   build_call_expr_loc (input_location,
-						built_in_decls[BUILT_IN_CLZLL],
+						built_in_decls (BUILT_IN_CLZLL),
 						1, tmp2));
       tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
 			      tmp2, ullsize);
@@ -4198,17 +4198,17 @@  gfc_conv_intrinsic_trailz (gfc_se * se, 
   if (argsize <= INT_TYPE_SIZE)
     {
       arg_type = unsigned_type_node;
-      func = built_in_decls[BUILT_IN_CTZ];
+      func = built_in_decls (BUILT_IN_CTZ);
     }
   else if (argsize <= LONG_TYPE_SIZE)
     {
       arg_type = long_unsigned_type_node;
-      func = built_in_decls[BUILT_IN_CTZL];
+      func = built_in_decls (BUILT_IN_CTZL);
     }
   else if (argsize <= LONG_LONG_TYPE_SIZE)
     {
       arg_type = long_long_unsigned_type_node;
-      func = built_in_decls[BUILT_IN_CTZLL];
+      func = built_in_decls (BUILT_IN_CTZLL);
     }
   else
     {
@@ -4259,7 +4259,7 @@  gfc_conv_intrinsic_trailz (gfc_se * se, 
       tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
       tmp1 = fold_convert (result_type,
 			   build_call_expr_loc (input_location,	
-						built_in_decls[BUILT_IN_CTZLL],
+						built_in_decls (BUILT_IN_CTZLL),
 						1, tmp1));
       tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
 			      tmp1, ullsize);
@@ -4267,7 +4267,7 @@  gfc_conv_intrinsic_trailz (gfc_se * se, 
       tmp2 = fold_convert (long_long_unsigned_type_node, arg);
       tmp2 = fold_convert (result_type,
 			   build_call_expr_loc (input_location,
-						built_in_decls[BUILT_IN_CTZLL],
+						built_in_decls (BUILT_IN_CTZLL),
 						1, tmp2));
 
       trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
@@ -4304,17 +4304,17 @@  gfc_conv_intrinsic_popcnt_poppar (gfc_se
   if (argsize <= INT_TYPE_SIZE)
     {
       arg_type = unsigned_type_node;
-      func = built_in_decls[parity ? BUILT_IN_PARITY : BUILT_IN_POPCOUNT];
+      func = built_in_decls (parity ? BUILT_IN_PARITY : BUILT_IN_POPCOUNT);
     }
   else if (argsize <= LONG_TYPE_SIZE)
     {
       arg_type = long_unsigned_type_node;
-      func = built_in_decls[parity ? BUILT_IN_PARITYL : BUILT_IN_POPCOUNTL];
+      func = built_in_decls (parity ? BUILT_IN_PARITYL : BUILT_IN_POPCOUNTL);
     }
   else if (argsize <= LONG_LONG_TYPE_SIZE)
     {
       arg_type = long_long_unsigned_type_node;
-      func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
+      func = built_in_decls (parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL);
     }
   else
     {
@@ -4327,7 +4327,7 @@  gfc_conv_intrinsic_popcnt_poppar (gfc_se
 	 as 'long long'.  */
       gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
 
-      func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
+      func = built_in_decls (parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL);
 
       /* Convert it to an integer, and store into a variable.  */
       utype = gfc_build_uint_type (argsize);
@@ -4580,7 +4580,7 @@  gfc_conv_intrinsic_isnan (gfc_se * se, g
 
   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   se->expr = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_ISNAN], 1, arg);
+			      built_in_decls (BUILT_IN_ISNAN), 1, arg);
   STRIP_TYPE_NOPS (se->expr);
   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
 }
@@ -5490,7 +5490,7 @@  gfc_conv_intrinsic_transfer (gfc_se * se
 
   /* Use memcpy to do the transfer.  */
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_MEMCPY],
+			 built_in_decls (BUILT_IN_MEMCPY),
 			 3,
 			 tmp,
 			 fold_convert (pvoid_type_node, source),
@@ -5535,7 +5535,7 @@  scalar_transfer:
       gfc_add_modify (&block, tmpdecl,
 		      fold_convert (TREE_TYPE (ptr), tmp));
       tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MEMCPY], 3,
+			     built_in_decls (BUILT_IN_MEMCPY), 3,
 			     fold_convert (pvoid_type_node, tmpdecl),
 			     fold_convert (pvoid_type_node, ptr),
 			     extent);
@@ -5560,7 +5560,7 @@  scalar_transfer:
       /* Use memcpy to do the transfer.  */
       tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
       tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MEMCPY], 3,
+			     built_in_decls (BUILT_IN_MEMCPY), 3,
 			     fold_convert (pvoid_type_node, tmp),
 			     fold_convert (pvoid_type_node, ptr),
 			     extent);
@@ -6001,7 +6001,7 @@  gfc_conv_intrinsic_repeat (gfc_se * se, 
   tmp = fold_build_pointer_plus_loc (input_location,
 				     fold_convert (pvoid_type_node, dest), tmp);
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MEMMOVE], 3, tmp, src,
+			     built_in_decls (BUILT_IN_MEMMOVE), 3, tmp, src,
 			     fold_build2_loc (input_location, MULT_EXPR,
 					      size_type_node, slen,
 					      fold_convert (size_type_node,
Index: gcc/function.c
===================================================================
--- gcc/function.c	(.../trunk)	(revision 179369)
+++ gcc/function.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -3638,7 +3638,7 @@  gimplify_parameters (void)
 		  DECL_IGNORED_P (addr) = 0;
 		  local = build_fold_indirect_ref (addr);
 
-		  t = built_in_decls[BUILT_IN_ALLOCA];
+		  t = built_in_decls (BUILT_IN_ALLOCA);
 		  t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm));
 		  /* The call has been built for a variable-sized object.  */
 		  CALL_ALLOCA_FOR_VAR_P (t) = 1;
Index: gcc/langhooks.c
===================================================================
--- gcc/langhooks.c	(.../trunk)	(revision 179369)
+++ gcc/langhooks.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -524,18 +524,15 @@  lhd_omp_firstprivatize_type_sizes (struc
 {
 }
 
-/* Common function for add_builtin_function and
-   add_builtin_function_ext_scope.  */
-static tree
-add_builtin_function_common (const char *name,
+/* Set up a builtin function without adding it to the front end's binding.  */
+tree
+add_builtin_function_nobind (tree id,
 			     tree type,
 			     int function_code,
 			     enum built_in_class cl,
 			     const char *library_name,
-			     tree attrs,
-			     tree (*hook) (tree))
+			     tree attrs)
 {
-  tree   id = get_identifier (name);
   tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, id, type);
 
   TREE_PUBLIC (decl)         = 1;
@@ -559,7 +556,7 @@  add_builtin_function_common (const char 
   else
     decl_attributes (&decl, NULL_TREE, 0);
 
-  return hook (decl);
+  return decl;
 
 }
 
@@ -573,9 +570,11 @@  add_builtin_function (const char *name,
 		      const char *library_name,
 		      tree attrs)
 {
-  return add_builtin_function_common (name, type, function_code, cl,
-				      library_name, attrs,
-				      lang_hooks.builtin_function);
+  tree id = get_identifier (name);
+  tree decl = add_builtin_function_nobind (id, type, function_code, cl,
+					   library_name, attrs);
+
+  return lang_hooks.builtin_function (decl);
 }
 
 /* Like add_builtin_function, but make sure the scope is the external scope.
@@ -593,9 +592,11 @@  add_builtin_function_ext_scope (const ch
 				const char *library_name,
 				tree attrs)
 {
-  return add_builtin_function_common (name, type, function_code, cl,
-				      library_name, attrs,
-				      lang_hooks.builtin_function_ext_scope);
+  tree id = get_identifier (name);
+  tree decl = add_builtin_function_nobind (id, type, function_code, cl,
+					   library_name, attrs);
+
+  return lang_hooks.builtin_function_ext_scope (decl);
 }
 
 tree
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	(.../trunk)	(revision 179369)
+++ gcc/langhooks.h	(.../branches/ibm/builtin)	(revision 179396)
@@ -490,4 +490,7 @@  extern tree add_builtin_function_ext_sco
 					    const char *library_name,
 					    tree attrs);
 
+extern tree add_builtin_function_nobind (tree id, tree type, int function_code,
+					 enum built_in_class cl,
+					 const char *library_name, tree attrs);
 #endif /* GCC_LANG_HOOKS_H */
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(.../trunk)	(revision 179369)
+++ gcc/c-typeck.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2766,7 +2766,7 @@  build_function_call_vec (location_t loc,
       && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP],
+      tree trap = build_function_call (loc, built_in_decls (BUILT_IN_TRAP),
 				       NULL_TREE);
       int i;
 
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(.../trunk)	(revision 179369)
+++ gcc/gimplify.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1109,12 +1109,12 @@  build_stack_save_restore (gimple *save, 
 {
   tree tmp_var;
 
-  *save = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0);
+  *save = gimple_build_call (implicit_built_in_decls (BUILT_IN_STACK_SAVE), 0);
   tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
   gimple_call_set_lhs (*save, tmp_var);
 
   *restore
-    = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
+    = gimple_build_call (implicit_built_in_decls (BUILT_IN_STACK_RESTORE),
 			 1, tmp_var);
 }
 
@@ -1329,7 +1329,7 @@  gimplify_vla_decl (tree decl, gimple_seq
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = built_in_decls[BUILT_IN_ALLOCA];
+  t = built_in_decls (BUILT_IN_ALLOCA);
   t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
   /* The call has been built for a variable-sized object.  */
   CALL_ALLOCA_FOR_VAR_P (t) = 1;
@@ -3210,7 +3210,7 @@  gimplify_modify_expr_to_memcpy (tree *ex
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
 
-  t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  t = implicit_built_in_decls (BUILT_IN_MEMCPY);
 
   gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
 
@@ -3257,7 +3257,7 @@  gimplify_modify_expr_to_memset (tree *ex
 
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
-  t = implicit_built_in_decls[BUILT_IN_MEMSET];
+  t = implicit_built_in_decls (BUILT_IN_MEMSET);
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
 
@@ -4680,7 +4680,7 @@  gimplify_variable_sized_compare (tree *e
   arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
   src = build_fold_addr_expr_loc (loc, op1);
   dest = build_fold_addr_expr_loc (loc, op0);
-  t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+  t = implicit_built_in_decls (BUILT_IN_MEMCMP);
   t = build_call_expr_loc (loc, t, 3, dest, src, arg);
 
   expr
@@ -7978,24 +7978,24 @@  gimplify_function_tree (tree fndecl)
       tree tmp_var;
       gimple call;
 
-      x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+      x = implicit_built_in_decls (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
       gimple_call_set_lhs (call, tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
+      x = implicit_built_in_decls (BUILT_IN_PROFILE_FUNC_EXIT);
       call = gimple_build_call (x, 2,
 				build_fold_addr_expr (current_function_decl),
 				tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
       tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
 
-      x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+      x = implicit_built_in_decls (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
       gimple_call_set_lhs (call, tmp_var);
       gimplify_seq_add_stmt (&body, call);
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
+      x = implicit_built_in_decls (BUILT_IN_PROFILE_FUNC_ENTER);
       call = gimple_build_call (x, 2,
 				build_fold_addr_expr (current_function_decl),
 				tmp_var);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(.../trunk)	(revision 179369)
+++ gcc/calls.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -274,6 +274,7 @@  emit_call_1 (rtx funexp, tree fntree ATT
   if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL)
     {
       tree t = fndecl;
+      tree bfndecl;
       /* Although a built-in FUNCTION_DECL and its non-__builtin
 	 counterpart compare equal and get a shared mem_attrs, they
 	 produce different dump output in compare-debug compilations,
@@ -282,8 +283,8 @@  emit_call_1 (rtx funexp, tree fntree ATT
 	 doesn't run the garbage collector at the same spot and then
 	 shares the mem_attr with the equivalent entry. */
       if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
-	  && built_in_decls[DECL_FUNCTION_CODE (t)])
-	t = built_in_decls[DECL_FUNCTION_CODE (t)];
+	  && (bfndecl = built_in_decls (DECL_FUNCTION_CODE (t))) != NULL_TREE)
+	t = bfndecl;
       set_mem_expr (funmem, t);
     }
   else if (fntree)
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(.../trunk)	(revision 179369)
+++ gcc/lto/lto-lang.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -499,9 +499,9 @@  def_builtin_1 (enum built_in_function fn
     add_builtin_function (libname, libtype, fncode, fnclass,
 			  NULL, fnattrs);
 
-  built_in_decls[(int) fncode] = decl;
+  built_in_set_decl (fncode, decl);
   if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
+    built_in_set_implicit (fncode, decl);
 }
 
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c	(.../trunk)	(revision 179369)
+++ gcc/tree-ssa-forwprop.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1596,7 +1596,7 @@  simplify_builtin_call (gimple_stmt_itera
 	      if (!is_gimple_val (ptr1))
 		ptr1 = force_gimple_operand_gsi (gsi_p, ptr1, true, NULL_TREE,
 						 true, GSI_SAME_STMT);
-	      gimple_call_set_fndecl (stmt2, built_in_decls [BUILT_IN_MEMCPY]);
+	      gimple_call_set_fndecl (stmt2, built_in_decls (BUILT_IN_MEMCPY));
 	      gimple_call_set_arg (stmt2, 0, ptr1);
 	      gimple_call_set_arg (stmt2, 1, new_str_cst);
 	      gimple_call_set_arg (stmt2, 2,
Index: gcc/tree-nested.c
===================================================================
--- gcc/tree-nested.c	(.../trunk)	(revision 179369)
+++ gcc/tree-nested.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1811,8 +1811,8 @@  convert_nl_goto_reference (gimple_stmt_i
   x = get_frame_field (info, target_context, field, &wi->gsi);
   x = build_addr (x, target_context);
   x = gsi_gimplify_val (info, x, &wi->gsi);
-  call = gimple_build_call (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2,
-			    build_addr (new_label, target_context), x);
+  call = gimple_build_call (implicit_built_in_decls (BUILT_IN_NONLOCAL_GOTO),
+			    2, build_addr (new_label, target_context), x);
   gsi_replace (&wi->gsi, call, false);
 
   /* We have handled all of STMT's operands, no need to keep going.  */
@@ -1924,7 +1924,7 @@  convert_tramp_reference_op (tree *tp, in
 
       /* Do machine-specific ugliness.  Normally this will involve
 	 computing extra alignment, but it can really be anything.  */
-      builtin = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
+      builtin = implicit_built_in_decls (BUILT_IN_ADJUST_TRAMPOLINE);
       call = gimple_build_call (builtin, 1, x);
       x = init_tmp_var_with_call (info, &wi->gsi, call);
 
@@ -2399,7 +2399,7 @@  finalize_nesting_tree_1 (struct nesting_
 		      root->frame_decl, field, NULL_TREE);
 	  arg1 = build_addr (x, context);
 
-	  x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
+	  x = implicit_built_in_decls (BUILT_IN_INIT_TRAMPOLINE);
 	  stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
 	  gimple_seq_add_stmt (&stmt_list, stmt);
 	}
Index: gcc/tree-ssa-loop-prefetch.c
===================================================================
--- gcc/tree-ssa-loop-prefetch.c	(.../trunk)	(revision 179369)
+++ gcc/tree-ssa-loop-prefetch.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1117,7 +1117,7 @@  issue_prefetch_ref (struct mem_ref *ref,
 					   NULL, true, GSI_SAME_STMT);
       }
       /* Create the prefetch instruction.  */
-      prefetch = gimple_build_call (built_in_decls[BUILT_IN_PREFETCH],
+      prefetch = gimple_build_call (built_in_decls (BUILT_IN_PREFETCH),
 				    3, addr, write_p, local);
       gsi_insert_before (&bsi, prefetch, GSI_SAME_STMT);
     }
@@ -1909,7 +1909,7 @@  tree_ssa_prefetch_arrays (void)
 
   initialize_original_copy_tables ();
 
-  if (!built_in_decls[BUILT_IN_PREFETCH])
+  if (!built_in_decls (BUILT_IN_PREFETCH))
     {
       tree type = build_function_type_list (void_type_node,
 					    const_ptr_type_node, NULL_TREE);
@@ -1917,7 +1917,7 @@  tree_ssa_prefetch_arrays (void)
 					BUILT_IN_PREFETCH, BUILT_IN_NORMAL,
 					NULL, NULL_TREE);
       DECL_IS_NOVOPS (decl) = true;
-      built_in_decls[BUILT_IN_PREFETCH] = decl;
+      built_in_set_decl (BUILT_IN_PREFETCH, decl);
     }
 
   /* We assume that size of cache line is a power of two, so verify this
Index: gcc/tree-streamer-in.c
===================================================================
--- gcc/tree-streamer-in.c	(.../trunk)	(revision 179369)
+++ gcc/tree-streamer-in.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -1049,7 +1049,7 @@  streamer_get_builtin_tree (struct lto_in
     {
       if (fcode >= END_BUILTINS)
 	fatal_error ("machine independent builtin code out of range");
-      result = built_in_decls[fcode];
+      result = built_in_decls (fcode);
       gcc_assert (result);
     }
   else if (fclass == BUILT_IN_MD)
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(.../trunk)	(revision 179369)
+++ gcc/config/sparc/sparc.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -6781,7 +6781,7 @@  sparc_gimplify_va_arg (tree valist, tree
     {
       tree tmp = create_tmp_var (type, "va_arg_tmp");
       tree dest_addr = build_fold_addr_expr (tmp);
-      tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+      tree copy = build_call_expr (implicit_built_in_decls (BUILT_IN_MEMCPY),
 				   3, dest_addr, addr, size_int (rsize));
       TREE_ADDRESSABLE (tmp) = 1;
       gimplify_and_add (copy, pre_p);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(.../trunk)	(revision 179369)
+++ gcc/config/i386/i386.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -7958,10 +7958,9 @@  ix86_gimplify_va_arg (tree valist, tree 
 		}
 	      else
 		{
-		  tree copy
-		    = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
-				       3, dest_addr, src_addr,
-				       size_int (cur_size));
+		  tree bfn = implicit_built_in_decls (BUILT_IN_MEMCPY);
+		  tree copy = build_call_expr (bfn, 3, dest_addr, src_addr,
+					       size_int (cur_size));
 		  gimplify_and_add (copy, pre_p);
 		}
 	      prev_size += cur_size;
@@ -28844,7 +28843,7 @@  ix86_veclibabi_svml (enum built_in_funct
       return NULL_TREE;
     }
 
-  bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls[fn]));
+  bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls (fn)));
 
   if (fn == BUILT_IN_LOGF)
     strcpy (name, "vmlsLn4");
@@ -28862,7 +28861,7 @@  ix86_veclibabi_svml (enum built_in_funct
   name[4] &= ~0x20;
 
   arity = 0;
-  for (args = DECL_ARGUMENTS (implicit_built_in_decls[fn]); args;
+  for (args = DECL_ARGUMENTS (implicit_built_in_decls (fn)); args;
        args = TREE_CHAIN (args))
     arity++;
 
@@ -28943,11 +28942,11 @@  ix86_veclibabi_acml (enum built_in_funct
       return NULL_TREE;
     }
 
-  bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls[fn]));
+  bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls (fn)));
   sprintf (name + 7, "%s", bname+10);
 
   arity = 0;
-  for (args = DECL_ARGUMENTS (implicit_built_in_decls[fn]); args;
+  for (args = DECL_ARGUMENTS (implicit_built_in_decls (fn)); args;
        args = TREE_CHAIN (args))
     arity++;
 
Index: gcc/config/vms/vms.c
===================================================================
--- gcc/config/vms/vms.c	(.../trunk)	(revision 179369)
+++ gcc/config/vms/vms.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -99,8 +99,8 @@  vms_patch_builtins (void)
   unsigned int i;
 
   /* Fwrite on VMS is non-standard.  */
-  implicit_built_in_decls[(int) BUILT_IN_FWRITE] = NULL_TREE;
-  implicit_built_in_decls[(int) BUILT_IN_FWRITE_UNLOCKED] = NULL_TREE;
+  built_in_set_implicit (BUILT_IN_WRITE, NULL_TREE);
+  built_in_set_implicit (BUILT_IN_WRITE_UNLOCKED, NULL_TREE);
 
   /* Define aliases for names.  */
   for (i = 0; i < NBR_CRTL_NAMES; i++)
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(.../trunk)	(revision 179369)
+++ gcc/config/ia64/ia64.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -10100,15 +10100,13 @@  ia64_init_builtins (void)
 
   if (TARGET_HPUX)
     {
-      if (built_in_decls [BUILT_IN_FINITE])
-	set_user_assembler_name (built_in_decls [BUILT_IN_FINITE],
-	  "_Isfinite");
-      if (built_in_decls [BUILT_IN_FINITEF])
-	set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF],
-	  "_Isfinitef");
-      if (built_in_decls [BUILT_IN_FINITEL])
-	set_user_assembler_name (built_in_decls [BUILT_IN_FINITEL],
-	  "_Isfinitef128");
+      tree bfn;
+      if ((bfn = built_in_decls (BUILT_IN_FINITE)) != NULL_TREE)
+	set_user_assembler_name (bfn, "_Isfinite");
+      if ((bfn = built_in_decls (BUILT_IN_FINITEF)) != NULL_TREE)
+	set_user_assembler_name (bfn, "_Isfinitef");
+      if ((bfn = built_in_decls (BUILT_IN_FINITEL)) != NULL_TREE)
+	set_user_assembler_name (bfn, "_Isfinitef128");
     }
 }
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../trunk)	(revision 179369)
+++ gcc/config/rs6000/rs6000.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2108,6 +2108,8 @@  rs6000_debug_reg_global (void)
 	   rs6000_long_double_type_size);
   fprintf (stderr, DEBUG_FMT_D, "sched_restricted_insns_priority",
 	   (int)rs6000_sched_restricted_insns_priority);
+  fprintf (stderr, DEBUG_FMT_D, "sizeof tree_function_decl",
+	   (int)sizeof (struct tree_function_decl));
 }
 
 /* Initialize the various global tables that are based on register size.  */
@@ -3739,7 +3741,7 @@  rs6000_builtin_vectorized_libmass (tree 
 	case BUILT_IN_SQRT:
 	case BUILT_IN_TAN:
 	case BUILT_IN_TANH:
-	  bdecl = implicit_built_in_decls[fn];
+	  bdecl = implicit_built_in_decls (fn);
 	  suffix = "d2";				/* pow -> powd2 */
 	  if (el_mode != DFmode
 	      || n != 2)
@@ -3776,7 +3778,7 @@  rs6000_builtin_vectorized_libmass (tree 
 	case BUILT_IN_SQRTF:
 	case BUILT_IN_TANF:
 	case BUILT_IN_TANHF:
-	  bdecl = implicit_built_in_decls[fn];
+	  bdecl = implicit_built_in_decls (fn);
 	  suffix = "4";					/* powf -> powf4 */
 	  if (el_mode != SFmode
 	      || n != 4)
@@ -9400,7 +9402,7 @@  rs6000_gimplify_va_arg (tree valist, tre
       tree tmp = create_tmp_var (type, "va_arg_tmp");
       tree dest_addr = build_fold_addr_expr (tmp);
 
-      tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+      tree copy = build_call_expr (implicit_built_in_decls (BUILT_IN_MEMCPY),
 				   3, dest_addr, addr, size_int (rsize * 4));
 
       gimplify_and_add (copy, pre_p);
@@ -12213,8 +12215,11 @@  rs6000_init_builtins (void)
 
 #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");
+  {
+    tree bfn = built_in_decls (BUILT_IN_CLOG);
+    if (bfn)
+      set_user_assembler_name (bfn, "__clog");
+  }
 #endif
 
 #ifdef SUBTARGET_INIT_BUILTINS
Index: gcc/config/darwin.c
===================================================================
--- gcc/config/darwin.c	(.../trunk)	(revision 179369)
+++ gcc/config/darwin.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -2962,7 +2962,7 @@  darwin_override_options (void)
 static void
 darwin_patch_builtin (int fncode)
 {
-  tree fn = built_in_decls[fncode];
+  tree fn = built_in_decls ((enum built_in_function)fncode);
   tree sym;
   char *newname;
 
@@ -2974,7 +2974,7 @@  darwin_patch_builtin (int fncode)
 
   set_user_assembler_name (fn, newname);
 
-  fn = implicit_built_in_decls[fncode];
+  fn = implicit_built_in_decls ((enum built_in_function)fncode);
   if (fn)
     set_user_assembler_name (fn, newname);
 }
@@ -3149,9 +3149,8 @@  darwin_rename_builtins (void)
      use the faster version.  */
   if (!flag_unsafe_math_optimizations)
     {
-      int dcode = (BUILT_IN_COMPLEX_DIV_MIN
-		   + DCmode - MIN_MODE_COMPLEX_FLOAT);
-      tree fn = built_in_decls[dcode];
+      tree fn = built_in_set_decl_add (BUILT_IN_COMPLEX_DIV_MIN,
+				       DCmode - MIN_MODE_COMPLEX_FLOAT);
       /* Fortran and c call TARGET_INIT_BUILTINS and
 	 TARGET_INIT_LIBFUNCS at different times, so we have to put a
 	 call into each to ensure that at least one of them is called
@@ -3159,7 +3158,7 @@  darwin_rename_builtins (void)
 	 new hook to run after build_common_builtin_nodes runs.  */
       if (fn)
 	set_user_assembler_name (fn, "___ieee_divdc3");
-      fn = implicit_built_in_decls[dcode];
+      fn = implicit_built_in_decls (dcode);
       if (fn)
 	set_user_assembler_name (fn, "___ieee_divdc3");
     }
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	(.../trunk)	(revision 179369)
+++ gcc/config/pa/pa.c	(.../branches/ibm/builtin)	(revision 179396)
@@ -555,16 +555,17 @@  static void
 pa_init_builtins (void)
 {
 #ifdef DONT_HAVE_FPUTC_UNLOCKED
-  built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] =
-    built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
-  implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED]
-    = implicit_built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
+  buil_in_copy_decl (BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_PUTC_UNLOCKED);
 #endif
 #if TARGET_HPUX_11
-  if (built_in_decls [BUILT_IN_FINITE])
-    set_user_assembler_name (built_in_decls [BUILT_IN_FINITE], "_Isfinite");
-  if (built_in_decls [BUILT_IN_FINITEF])
-    set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef");
+  {
+    tree bfn;
+
+    if ((bfn = built_in_decls (BUILT_IN_FINITE)) != NULL_TREE)
+      set_user_assembler_name (bfn, "_Isfinite");
+    if ((bfn = built_in_decls (BUILT_IN_FINITEF)) != NULL_TREE)
+      set_user_assembler_name (bfn, "_Isfinitef");
+  }
 #endif
 
   if (HPUX_LONG_DOUBLE_LIBRARY)