[PATCH] Add attribute((target("..."))) and pragma target to PowerPC

Michael Meissner meissner@linux.vnet.ibm.com
Sun Oct 31 20:28:00 GMT 2010


This patch extends my previous patch here:
http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01952.html

to include the initial PowerPC support for __attribute__((__target__("...")))
and for #pragma GCC target "...".

The machine independent portion of the patch is mostly the same as I previously
submitted, except I reworked the awk scripts as suggested by Ralf Wildenhues to
not do a-z or A-Z inside of regexps, instead using the letters spelled out.

The PowerPC support includes the initial support for the target attribute and
pragma, mostly cloning it from the work I did in GCC 4.3 to add the support to
the i386/x86_64 ports.  The one thing that is not currently done is I didn't
look into the builtin function generation, nor into #defining and #undef'ing
target macros for the #pragmas.

I did a bootstrap on C, C++, and Fortran front ends, and ran the regression
test for C and Fortran (the C++ library tests were all failing on the powerpc
when I took my snapshot).  I only had one regression (gcc.dg/sms-3.c fails
under -m32 now when it used to pass for the selective scheduler).  Is this ok
to install?

The first attachment will be the machine independent patches, and the second
will by the PowerPC patches.

[gcc]
2010-10-31  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* doc/options.texi (Option file format): Document TargetVariable,
	HeaderInclude, and SourceInclude.
	* optc-gen.awk: Add support for TargetVariable, HeaderInclude, and
	SourceInclude.  Add GTY(()) on main option structure for the
	compiler proper, but not in the driver file.
	* opth-gen.awk: Ditto.

	* configure.ac: Figure out the additional include files specified
	by the HeaderInclude and SourceInclude options directives.
	* configure: Regenerate.

	* Makefile.in (OPTIONS_H_EXTRA): New make variable for HeaderInclude.
	(OPTIONS_C_EXTRA): New make variable for SourceInclude.
	(@options_include@): Add the include files if any specified by the
	various .opt files.
	(OPTIONS_H): New make variable for options.h and any files it
	includes.
	(TREE_H): Use $(OPTIONS_H) instead of options.h.
	(FLAGS_H): Ditto.
	(c-family/c-opts.o): Ditto.
	(lto-opts.o): Ditto.
	(opts.o): Ditto.
	(opts-common.o): Ditto.
	(options.o): Add $(OPTIONS_C_EXTRA) to the dependencies.
	(gcc-options.o): Ditto.

	* opt-include.awk: New awk script to output the include files
	specified by option HeaderInclude and SourceInclude options.

	* config/rs6000/aix.opt (-mxl-compat): Make option Saved.
	* config/rs6000/aix64.opt (-mpe): Ditto.
	* config/rs6000/linux64.opt (-mprofile-kernel): Ditto.
	* config/rs6000/sysv4.opt (-mbit-align): Ditto.
	(-mprototype): Ditto.
	(-mbit-word): Ditto.
	(-mregnames): Ditto.
	(-msecure-plt): Ditto.
	(-mbss-plt): Ditto.
	* config/rs6000/rs6000.opt (-mpowerpc-gpopt): Ditto.
	(-mpowerpc-gfxopt): Ditto.
	(-mmfcrf): Ditto.
	(-mpopcntb): Ditto.
	(-mfprnd): Ditto.
	(-mcmpb): Ditto.
	(-mmfpgpr): Ditto.
	(-maltivec): Ditto.
	(-mhard-dfp): Ditto.
	(-mmulhw): Ditto.
	(-mdlmzb): Ditto.
	(-mmultiple): Ditto.
	(-mstring): Ditto.
	(-mpopcntd): Ditto.
	(-mfriz): Ditto.
	(-mvsx): Ditto.
	(-mno-update): Ditto.
	(-mavoid-indexed-addresses): Ditto.
	(-mfused-madd): Ditto.
	(-mtls-markers): Ditto.
	(-msched-prolog): Ditto.
	(-maix-struct-return): Ditto.
	(-msvr4-struct-return): Ditto.
	(-mxl-compat): Ditto.
	(-mrecip-precision): Ditto.
	(-mno-fp-in-toc): Ditto.
	(-mno-sum-in-toc): Ditto.
	(-mvrsave): Ditto.
	(-mblock-move-inline-limit=): Ditto.
	(-misel): Ditto.
	(-mspe): Ditto.
	(-mpaired): Ditto.
	(-mlongcall): Ditto.
	(-mgen-cell-microcode): Ditto.
	(-mwarn-cell-microcode): Ditto.
	(-mwarn-altivec-long): Ditto.
	(-mprioritize-restricted-insns=): Ditto.
	(-msingle-float): Ditto.
	(-mdouble-float): Ditto.
	(-msimple-fpu): Ditto.
	(-mxilinx-fpu): Ditto.
	(rs6000_cpu_index): New target variable for -mcpu= index.
	(rs6000_tune_index): New target variable for -mtune= index.
	(rs6000_target_flags_explicit): New save area for
	target_flags_explicit.

	* config/rs6000/rs6000-protos.h (rs6000_pragma_target_parse): New
	declaration.

	* config/rs6000/rs6000.c (rs6000_tls_size_string): Delete.
	(rs6000_debug_name): Ditto.
	(rs6000_traceback_name): Ditto.
	(rs6000_parse_tls_size_option): Ditto.
	(TARGET_OPTION_VALID_ATTRIBUTE_P): Define for target attributes
	and pragma support.
	(TARGET_OPTION_SAVE): Ditto.
	(TARGET_OPTION_RESTORE): Ditto.
	(TARGET_OPTION_PRINT): Ditto.
	(TARGET_CAN_INLINE_P): Ditto.
	(TARGET_SET_CURRENT_FUNCTION): Ditto.
	(struct ptt): Move to file level scope.
	(processor_target_table): Ditto.
	(rs6000_cpu_name_lookup): New function, lookup cpu name in
	processor table, return index.
	(rs6000_option_override_internal): Don't take default cpu, instead
	take bool to say if this is the global initialization or target
	attributes/pragmas.  Adjust for being called multiple times.  Move
	the processor_target_table to file scope.  Move some of the string
	validations to rs6000_handle_options.  Save the initial target
	option nodes.
	(rs6000_option_override): Adjust rs6000_option_override_internal
	call.
	(rs6000_handle_option): Move some of the string validations here,
	from rs6000_option_override_internal.  Adjust for target
	attributes and pragmas.  Add -mdebug=target.
	(rs6000_conditional_register_usage): Print trace message if
	-mdebug=reg or -mdebug=target.
	(rs6000_opt_masks): New lookup table for mask options that are
	available for target attributes/pragmas.
	(rs6000_inner_target_options): New function to support target
	attributes/pragmas.
	(rs6000_debug_target_options): Ditto.
	(rs6000_valid_attribute_p): Ditto.
	(rs6000_pragma_target_parse): Ditto.
	(rs6000_set_current_function): Ditto.
	(rs6000_function_specific_save): Ditto.
	(rs6000_function_specific_restore): Ditto.
	(rs6000_function_specific_print): Ditto.
	(rs6000_can_inline_p): Ditto.

	* config/rs6000/rs6000.opt (HeaderInclude): Include rs6000-opts.h.
	(rs6000_cpu): Move definition here as a TargetVariable, from
	rs6000.c.
	(rs6000_always_hint): Ditto.
	(rs6000_sched_groups): Ditto.
	(rs6000_align_branch_targets): Ditto.
	(rs6000_sched_costly_dep): Ditto.
	(rs6000_sched_insert_nops): Ditto.
	(rs6000_long_double_type_size): Ditto.
	(rs6000_ieeequad): Ditto.
	(rs6000_spe): Ditto.
	(rs6000_spe_abi): Ditto.
	(rs6000_float_gprs): Ditto.
	(rs6000_darwin64_abi): Ditto.
	(rs6000_sdata): Ditto.
	(rs6000_tls_size): Ditto.
	(rs6000_current_abi): Ditto.
	(rs6000_tracebback): Ditto.
	(rs6000_alignment_flags): Ditto.
	(rs6000_recip_control): Ditto.
	(rs6000_current_cmode): Rename from cmodel.  Move definition here
	as a TargetVariable, from rs6000.c.
	(rs6000_debug): Combine separate debug flags to a single
	variable.

	* config/rs6000/linux64.h (cmodel): Delete.
	(TARGET_CMODE): Change cmodel to rs6000_current_cmodel.
	(SUBSUBTARGET_OVERRIDE_OPTIONS): Ditto.

	* config/rs6000/rs6000.c (rs6000_cpu): Move definition to
	rs6000.opt as TargetVariables.
	(rs6000_always_hint): Ditto.
	(rs6000_sched_groups): Ditto.
	(rs6000_align_branch_targets): Ditto.
	(rs6000_sched_costly_dep): Ditto.
	(rs6000_sched_insert_nops): Ditto.
	(rs6000_long_double_type_size): Ditto.
	(rs6000_ieeequad): Ditto.
	(rs6000_spe): Ditto.
	(rs6000_spe_abi): Ditto.
	(rs6000_float_gprs): Ditto.
	(rs6000_darwin64_abi): Ditto.
	(rs6000_sdata): Ditto.
	(rs6000_tls_size): Ditto.
	(rs6000_current_abi): Ditto.
	(rs6000_tracebback): Ditto.
	(rs6000_alignment_flags): Ditto.
	(rs6000_recip_control): Ditto.
	(rs6000_current_cmode): Rename from cmodel.  Move to rs6000.opt.
	(rs6000_sched_insert_nops_str): Make static.
	(rs6000_sched_costly_dep_str): Ditto.
	(rs6000_tls_size_string): Ditto.
	(rs6000_debug_name): Ditto.
	(rs6000_traceback_name): Ditto.
	(rs6000_recip_name): Ditto.
	(rs6000_debug_stack): Delete, combine debug flags into a single
	variable.  Allow -mdebug=foo,bar.
	(rs6000_debug_arg): Ditto.
	(rs6000_debug_reg): Ditto.
	(rs6000_debug_addr): Ditto.
	(rs6000_debug_cost): Ditto.
	(rs6000_option_override_internal): Ditto.
	(traceback enum): Move to rs6000-opts.h.
	(rs6000_handle_option): Rename cmodel to rs6000_current_cmodel.

	* gcc/config/rs6000/rs6000.h (toplevel): Include rs6000-opts.h if
	it hasn't already been included.
	(enum rs6000_cmodel): Move enumerations to rs6000-opts.h so they
	can be used by target variables.
	(enum processor_type): Ditto.
	(enum fpu_type_t): Ditto.
	(enum rs6000_dependence_cost): Ditto.
	(enum rs6000_nop_insertion): Ditto.
	(enum group_formation): Ditto.
	(enum rs6000_vector): Ditto.
	(enum rs6000_abi): Ditto.
	(TARGET_DEBUG_*): Use a single rs6000_debug variable instead of
	having a separate variable for each debug flag.  Add
	-mdebug=target support.
	(rs6000_cpu): Delete variable definitons that are now defined as
	TargetVariables in rs6000.opt.
	(rs6000_long_double_type_size): Ditto.
	(rs6000_ieeequad): Ditto.
	(rs6000_altivec_abi): Ditto.
	(rs6000_spe_abi): Ditto.
	(rs6000_spe): Ditto.
	(rs6000_float_gprs): Ditto.
	(rs6000_alignment_flags): Ditto.
	(rs6000_current_abi): Ditto.
	(rs6000_sched_insert_nop_str): Delete.
	(REGISTER_TARGET_PRAGMAS): Register the pragma target handler.

	* gcc/config/rs6000/rs6000-opts.h: New file.  Move all enums here
	from rs6000.h and sysv4.h to allow target variables to be declared
	as enums.

	* gcc/config/rs6000/sysv4.h (enum rs6000_sdata_type): Move to
	rs6000-opts.h.
	(rs6000_sdata): Delete, this is now a TargetVariable.
	(rs6000_tls_size_string): Ditto.
	(rs6000_abi_name): Delete.
	(rs6000_sdata_name): Ditto.

[gcc/testsuite]
2010-10-31  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/ppc-target-1.c: New file to test powerpc
	target attribute.

	* gcc.target/powerpc/ppc-target-2.c: New file to test powerpc
	target pragma.



-- 
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
meissner@linux.vnet.ibm.com
-------------- next part --------------
[gcc]
2010-10-31  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* doc/options.texi (Option file format): Document TargetVariable,
	HeaderInclude, and SourceInclude.
	* optc-gen.awk: Add support for TargetVariable, HeaderInclude, and
	SourceInclude.  Add GTY(()) on main option structure for the
	compiler proper, but not in the driver file.
	* opth-gen.awk: Ditto.

	* configure.ac: Figure out the additional include files specified
	by the HeaderInclude and SourceInclude options directives.
	* configure: Regenerate.

	* Makefile.in (OPTIONS_H_EXTRA): New make variable for HeaderInclude.
	(OPTIONS_C_EXTRA): New make variable for SourceInclude.
	(@options_include@): Add the include files if any specified by the
	various .opt files.
	(OPTIONS_H): New make variable for options.h and any files it
	includes.
	(TREE_H): Use $(OPTIONS_H) instead of options.h.
	(FLAGS_H): Ditto.
	(c-family/c-opts.o): Ditto.
	(lto-opts.o): Ditto.
	(opts.o): Ditto.
	(opts-common.o): Ditto.
	(options.o): Add $(OPTIONS_C_EXTRA) to the dependencies.
	(gcc-options.o): Ditto.

	* opt-include.awk: New awk script to output the include files
	specified by option HeaderInclude and SourceInclude options.

	* config/rs6000/aix.opt (-mxl-compat): Make option Saved.
	* config/rs6000/aix64.opt (-mpe): Ditto.
	* config/rs6000/linux64.opt (-mprofile-kernel): Ditto.
	* config/rs6000/sysv4.opt (-mbit-align): Ditto.
	(-mprototype): Ditto.
	(-mbit-word): Ditto.
	(-mregnames): Ditto.
	(-msecure-plt): Ditto.
	(-mbss-plt): Ditto.
	* config/rs6000/rs6000.opt (-mpowerpc-gpopt): Ditto.
	(-mpowerpc-gfxopt): Ditto.
	(-mmfcrf): Ditto.
	(-mpopcntb): Ditto.
	(-mfprnd): Ditto.
	(-mcmpb): Ditto.
	(-mmfpgpr): Ditto.
	(-maltivec): Ditto.
	(-mhard-dfp): Ditto.
	(-mmulhw): Ditto.
	(-mdlmzb): Ditto.
	(-mmultiple): Ditto.
	(-mstring): Ditto.
	(-mpopcntd): Ditto.
	(-mfriz): Ditto.
	(-mvsx): Ditto.
	(-mno-update): Ditto.
	(-mavoid-indexed-addresses): Ditto.
	(-mfused-madd): Ditto.
	(-mtls-markers): Ditto.
	(-msched-prolog): Ditto.
	(-maix-struct-return): Ditto.
	(-msvr4-struct-return): Ditto.
	(-mxl-compat): Ditto.
	(-mrecip-precision): Ditto.
	(-mno-fp-in-toc): Ditto.
	(-mno-sum-in-toc): Ditto.
	(-mvrsave): Ditto.
	(-mblock-move-inline-limit=): Ditto.
	(-misel): Ditto.
	(-mspe): Ditto.
	(-mpaired): Ditto.
	(-mlongcall): Ditto.
	(-mgen-cell-microcode): Ditto.
	(-mwarn-cell-microcode): Ditto.
	(-mwarn-altivec-long): Ditto.
	(-mprioritize-restricted-insns=): Ditto.
	(-msingle-float): Ditto.
	(-mdouble-float): Ditto.
	(-msimple-fpu): Ditto.
	(-mxilinx-fpu): Ditto.
	(rs6000_cpu_index): New target variable for -mcpu= index.
	(rs6000_tune_index): New target variable for -mtune= index.
	(rs6000_target_flags_explicit): New save area for
	target_flags_explicit.

	* config/rs6000/rs6000-protos.h (rs6000_pragma_target_parse): New
	declaration.

	* config/rs6000/rs6000.c (rs6000_tls_size_string): Delete.
	(rs6000_debug_name): Ditto.
	(rs6000_traceback_name): Ditto.
	(rs6000_parse_tls_size_option): Ditto.
	(TARGET_OPTION_VALID_ATTRIBUTE_P): Define for target attributes
	and pragma support.
	(TARGET_OPTION_SAVE): Ditto.
	(TARGET_OPTION_RESTORE): Ditto.
	(TARGET_OPTION_PRINT): Ditto.
	(TARGET_CAN_INLINE_P): Ditto.
	(TARGET_SET_CURRENT_FUNCTION): Ditto.
	(struct ptt): Move to file level scope.
	(processor_target_table): Ditto.
	(rs6000_cpu_name_lookup): New function, lookup cpu name in
	processor table, return index.
	(rs6000_option_override_internal): Don't take default cpu, instead
	take bool to say if this is the global initialization or target
	attributes/pragmas.  Adjust for being called multiple times.  Move
	the processor_target_table to file scope.  Move some of the string
	validations to rs6000_handle_options.  Save the initial target
	option nodes.
	(rs6000_option_override): Adjust rs6000_option_override_internal
	call.
	(rs6000_handle_option): Move some of the string validations here,
	from rs6000_option_override_internal.  Adjust for target
	attributes and pragmas.  Add -mdebug=target.
	(rs6000_conditional_register_usage): Print trace message if
	-mdebug=reg or -mdebug=target.
	(rs6000_opt_masks): New lookup table for mask options that are
	available for target attributes/pragmas.
	(rs6000_inner_target_options): New function to support target
	attributes/pragmas.
	(rs6000_debug_target_options): Ditto.
	(rs6000_valid_attribute_p): Ditto.
	(rs6000_pragma_target_parse): Ditto.
	(rs6000_set_current_function): Ditto.
	(rs6000_function_specific_save): Ditto.
	(rs6000_function_specific_restore): Ditto.
	(rs6000_function_specific_print): Ditto.
	(rs6000_can_inline_p): Ditto.

	* config/rs6000/rs6000.opt (HeaderInclude): Include rs6000-opts.h.
	(rs6000_cpu): Move definition here as a TargetVariable, from
	rs6000.c.
	(rs6000_always_hint): Ditto.
	(rs6000_sched_groups): Ditto.
	(rs6000_align_branch_targets): Ditto.
	(rs6000_sched_costly_dep): Ditto.
	(rs6000_sched_insert_nops): Ditto.
	(rs6000_long_double_type_size): Ditto.
	(rs6000_ieeequad): Ditto.
	(rs6000_spe): Ditto.
	(rs6000_spe_abi): Ditto.
	(rs6000_float_gprs): Ditto.
	(rs6000_darwin64_abi): Ditto.
	(rs6000_sdata): Ditto.
	(rs6000_tls_size): Ditto.
	(rs6000_current_abi): Ditto.
	(rs6000_tracebback): Ditto.
	(rs6000_alignment_flags): Ditto.
	(rs6000_recip_control): Ditto.
	(rs6000_current_cmode): Rename from cmodel.  Move definition here
	as a TargetVariable, from rs6000.c.
	(rs6000_debug): Combine separate debug flags to a single
	variable.

	* config/rs6000/linux64.h (cmodel): Delete.
	(TARGET_CMODE): Change cmodel to rs6000_current_cmodel.
	(SUBSUBTARGET_OVERRIDE_OPTIONS): Ditto.

	* config/rs6000/rs6000.c (rs6000_cpu): Move definition to
	rs6000.opt as TargetVariables.
	(rs6000_always_hint): Ditto.
	(rs6000_sched_groups): Ditto.
	(rs6000_align_branch_targets): Ditto.
	(rs6000_sched_costly_dep): Ditto.
	(rs6000_sched_insert_nops): Ditto.
	(rs6000_long_double_type_size): Ditto.
	(rs6000_ieeequad): Ditto.
	(rs6000_spe): Ditto.
	(rs6000_spe_abi): Ditto.
	(rs6000_float_gprs): Ditto.
	(rs6000_darwin64_abi): Ditto.
	(rs6000_sdata): Ditto.
	(rs6000_tls_size): Ditto.
	(rs6000_current_abi): Ditto.
	(rs6000_tracebback): Ditto.
	(rs6000_alignment_flags): Ditto.
	(rs6000_recip_control): Ditto.
	(rs6000_current_cmode): Rename from cmodel.  Move to rs6000.opt.
	(rs6000_sched_insert_nops_str): Make static.
	(rs6000_sched_costly_dep_str): Ditto.
	(rs6000_tls_size_string): Ditto.
	(rs6000_debug_name): Ditto.
	(rs6000_traceback_name): Ditto.
	(rs6000_recip_name): Ditto.
	(rs6000_debug_stack): Delete, combine debug flags into a single
	variable.  Allow -mdebug=foo,bar.
	(rs6000_debug_arg): Ditto.
	(rs6000_debug_reg): Ditto.
	(rs6000_debug_addr): Ditto.
	(rs6000_debug_cost): Ditto.
	(rs6000_option_override_internal): Ditto.
	(traceback enum): Move to rs6000-opts.h.
	(rs6000_handle_option): Rename cmodel to rs6000_current_cmodel.

	* gcc/config/rs6000/rs6000.h (toplevel): Include rs6000-opts.h if
	it hasn't already been included.
	(enum rs6000_cmodel): Move enumerations to rs6000-opts.h so they
	can be used by target variables.
	(enum processor_type): Ditto.
	(enum fpu_type_t): Ditto.
	(enum rs6000_dependence_cost): Ditto.
	(enum rs6000_nop_insertion): Ditto.
	(enum group_formation): Ditto.
	(enum rs6000_vector): Ditto.
	(enum rs6000_abi): Ditto.
	(TARGET_DEBUG_*): Use a single rs6000_debug variable instead of
	having a separate variable for each debug flag.  Add
	-mdebug=target support.
	(rs6000_cpu): Delete variable definitons that are now defined as
	TargetVariables in rs6000.opt.
	(rs6000_long_double_type_size): Ditto.
	(rs6000_ieeequad): Ditto.
	(rs6000_altivec_abi): Ditto.
	(rs6000_spe_abi): Ditto.
	(rs6000_spe): Ditto.
	(rs6000_float_gprs): Ditto.
	(rs6000_alignment_flags): Ditto.
	(rs6000_current_abi): Ditto.
	(rs6000_sched_insert_nop_str): Delete.
	(REGISTER_TARGET_PRAGMAS): Register the pragma target handler.

	* gcc/config/rs6000/rs6000-opts.h: New file.  Move all enums here
	from rs6000.h and sysv4.h to allow target variables to be declared
	as enums.

	* gcc/config/rs6000/sysv4.h (enum rs6000_sdata_type): Move to
	rs6000-opts.h.
	(rs6000_sdata): Delete, this is now a TargetVariable.
	(rs6000_tls_size_string): Ditto.
	(rs6000_abi_name): Delete.
	(rs6000_sdata_name): Ditto.

[gcc/testsuite]
2010-10-31  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/ppc-target-1.c: New file to test powerpc
	target attribute.

	* gcc.target/powerpc/ppc-target-2.c: New file to test powerpc
	target pragma.

Index: gcc/doc/options.texi
===================================================================
--- gcc/doc/options.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/doc/options.texi	(working copy)
@@ -52,6 +52,32 @@ for variables set in option handlers rat
 @code{Var} properties.
 
 @item
+A variable record to define a variable used to store option
+information.  These records have two fields: the string
+@samp{TargetVariable}, and a declaration of the type and name of the
+variable, optionally with an initializer (but without any trailing
+@samp{;}).  @samp{TargetVariable} is a combination of @samp{Variable}
+and @samp{TargetSave} records in that the variable is defined in the
+@code{gcc_options} structure, but these variables are also stored in
+the @code{cl_target_option} structure.  The variables are saved in the
+target save code and restored in the target restore code.
+
+@item
+A variable record to record any additional files that the
+@file{options.h} file should include.  This is useful to provide
+enumeration or structure definitions needed for target variables.
+These records have two fields: the string @samp{HeaderInclude} and the
+name of the include file.
+
+@item
+A variable record to record any additional files that the
+@file{options.c} file should include.  This is useful to provide
+inline functions needed for target variables and/or @code{#ifdef}
+sequences to properly set up the initialization.  These records have
+two fields: the string @samp{SourceInclude} and the name of the
+include file.
+
+@item
 An option definition record.  These records have the following fields:
 @enumerate
 @item
Index: gcc/configure
===================================================================
--- gcc/configure	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/configure	(working copy)
@@ -853,7 +853,8 @@ PACKAGE_TARNAME
 PACKAGE_NAME
 PATH_SEPARATOR
 SHELL'
-ac_subst_files='language_hooks'
+ac_subst_files='option_includes
+language_hooks'
 ac_user_opts='
 enable_option_checking
 with_build_libsubdir
@@ -10498,8 +10499,10 @@ fi
 
 # Convert extra_options into a form suitable for Makefile use.
 extra_opt_files=
+all_opt_files=
 for f in $extra_options; do
   extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+  all_opt_files="$all_opt_files $srcdir/config/$f"
 done
 
 
@@ -17143,7 +17146,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17146 "configure"
+#line 17149 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17249,7 +17252,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17252 "configure"
+#line 17255 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -25483,6 +25486,7 @@ do
 	all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
 	if test -f $srcdir/$gcc_subdir/lang.opt; then
 	    lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+	    all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
 	fi
 	if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
 	    lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
@@ -25546,6 +25550,14 @@ do
 done
 
 # --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+
+
+# --------
 # UNSORTED
 # --------
 
@@ -27214,3 +27226,4 @@ if test -n "$ac_unrecognized_opts" && te
 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
 fi
 
+
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/configure.ac	(working copy)
@@ -1396,8 +1396,10 @@ fi
 
 # Convert extra_options into a form suitable for Makefile use.
 extra_opt_files=
+all_opt_files=
 for f in $extra_options; do
   extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+  all_opt_files="$all_opt_files $srcdir/config/$f"
 done
 AC_SUBST(extra_opt_files)
 
@@ -4448,6 +4450,7 @@ changequote([,])dnl
 	all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
 	if test -f $srcdir/$gcc_subdir/lang.opt; then
 	    lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+	    all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
 	fi
 	if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
 	    lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
@@ -4509,6 +4512,14 @@ do
 done
 
 # --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+AC_SUBST_FILE(option_includes)
+
+# --------
 # UNSORTED
 # --------
 
@@ -4771,3 +4782,4 @@ done
 ], 
 [subdirs='$subdirs'])
 AC_OUTPUT
+
Index: gcc/opt-include.awk
===================================================================
--- gcc/opt-include.awk	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 0)
+++ gcc/opt-include.awk	(revision 166071)
@@ -0,0 +1,30 @@
+#  Copyright (C) 2010
+#  Free Software Foundation, Inc.
+#  Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records and emits the include files
+# listed by the HeaderInclude directive.
+
+BEGIN {
+	h_next = 0
+	c_next = 0
+}
+
+(h_next != 0)	  { print "OPTIONS_H_EXTRA += $(srcdir)/" $1; h_next = 0 }
+(c_next != 0)	  { print "OPTIONS_C_EXTRA += $(srcdir)/" $1; c_next = 0 }
+/^HeaderInclude$/ { h_next = 1; c_next = 0 }
+/^SourceInclude$/ { h_next = 0; c_next = 1 }
Index: gcc/optc-gen.awk
===================================================================
--- gcc/optc-gen.awk	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/optc-gen.awk	(working copy)
@@ -31,7 +31,10 @@ BEGIN {
 	n_langs = 0
 	n_target_save = 0
 	n_extra_vars = 0
-        quote = "\042"
+	n_extra_target_vars = 0
+	n_extra_c_includes = 0
+	n_extra_h_includes = 0
+	quote = "\042"
 	comma = ","
 	FS=SUBSEP
 	# Default the name of header created from opth-gen.awk to options.h
@@ -53,6 +56,30 @@ BEGIN {
 			extra_vars[n_extra_vars] = $2
 			n_extra_vars++
 		}
+		else if ($1 == "TargetVariable") {
+			# Combination of TargetSave and Variable
+			extra_vars[n_extra_vars] = $2
+			n_extra_vars++
+
+			var = $2
+			sub(" *=.*", "", var)
+			orig_var = var
+			name = var
+			type = var
+			sub("^.*[ *]", "", name)
+			sub(" *" name "$", "", type)
+			target_save_decl[n_target_save] = type " x_" name
+			n_target_save++
+
+			extra_target_vars[n_extra_target_vars] = name
+			n_extra_target_vars++;
+		}
+		else if ($1 == "HeaderInclude") {
+			extra_h_includes[n_extra_h_includes++] = $2;
+		}
+		else if ($1 == "SourceInclude")  {
+			extra_c_includes[n_extra_c_includes++] = $2;
+		}
 		else {
 			name = opt_args("Mask", $1)
 			if (name == "") {
@@ -82,7 +109,17 @@ print "#include " quote "target.h" quote
 print "#endif /* GCC_DRIVER */"
 print ""
 
+if (n_extra_c_includes > 0) {
+	for (i = 0; i < n_extra_c_includes; i++) {
+		print "#include " quote extra_c_includes[i] quote
+	}
+	print ""
+}
+
 have_save = 0;
+if (n_extra_target_vars)
+	have_save = 1
+
 print "const struct gcc_options global_options_init =\n{"
 for (i = 0; i < n_extra_vars; i++) {
 	var = extra_vars[i]
@@ -304,6 +341,7 @@ print "{";
 n_opt_char = 2;
 n_opt_short = 0;
 n_opt_int = 0;
+n_opt_enum = 0;
 n_opt_other = 0;
 var_opt_char[0] = "optimize";
 var_opt_char[1] = "optimize_size";
@@ -330,6 +368,9 @@ for (i = 0; i < n_opts; i++) {
 		else if (otype ~ "^((un)?signed +)?short *$")
 			var_opt_short[n_opt_short++] = name;
 
+		else if (otype ~ ("^enum +[_" alnum "]+ *"))
+			var_opt_enum[n_opt_enum++] = name;
+
 		else if (otype ~ "^((un)?signed +)?char *$") {
 			var_opt_char[n_opt_char++] = name;
 			if (otype ~ "^unsigned +char *$")
@@ -353,6 +394,10 @@ for (i = 0; i < n_opt_other; i++) {
 	print "  ptr->x_" var_opt_other[i] " = opts->x_" var_opt_other[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  ptr->x_" var_opt_enum[i] " = opts->x_" var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_int; i++) {
 	print "  ptr->x_" var_opt_int[i] " = opts->x_" var_opt_int[i] ";";
 }
@@ -377,6 +422,10 @@ for (i = 0; i < n_opt_other; i++) {
 	print "  opts->x_" var_opt_other[i] " = ptr->x_" var_opt_other[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  ptr->x_" var_opt_enum[i] " = opts->x_" var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_int; i++) {
 	print "  opts->x_" var_opt_int[i] " = ptr->x_" var_opt_int[i] ";";
 }
@@ -410,6 +459,15 @@ for (i = 0; i < n_opt_other; i++) {
 	print "";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  if (ptr->x_" var_opt_enum[i] ")";
+	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
+	print "             indent_to, \"\",";
+	print "             \"" var_opt_enum[i] "\",";
+	print "             ptr->x_" var_opt_enum[i] ");";
+	print "";
+}
+
 for (i = 0; i < n_opt_int; i++) {
 	print "  if (ptr->x_" var_opt_int[i] ")";
 	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
@@ -448,6 +506,7 @@ print "{";
 n_target_char = 0;
 n_target_short = 0;
 n_target_int = 0;
+n_target_enum = 0;
 n_target_other = 0;
 
 if (have_save) {
@@ -468,6 +527,9 @@ if (have_save) {
 			else if (otype ~ "^((un)?signed +)?short *$")
 				var_target_short[n_target_short++] = name;
 
+			else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+				var_target_enum[n_target_enum++] = name;
+
 			else if (otype ~ "^((un)?signed +)?char *$") {
 				var_target_char[n_target_char++] = name;
 				if (otype ~ "^unsigned +char *$")
@@ -499,10 +561,18 @@ print "  if (targetm.target_option.save)
 print "    targetm.target_option.save (ptr);";
 print "";
 
+for (i = 0; i < n_extra_target_vars; i++) {
+	print "  ptr->x_" extra_target_vars[i] " = opts->x_" extra_target_vars[i] ";";
+}
+
 for (i = 0; i < n_target_other; i++) {
 	print "  ptr->x_" var_target_other[i] " = opts->x_" var_target_other[i] ";";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  ptr->x_" var_target_enum[i] " = opts->x_" var_target_enum[i] ";";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  ptr->x_" var_target_int[i] " = opts->x_" var_target_int[i] ";";
 }
@@ -523,10 +593,18 @@ print "void";
 print "cl_target_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)";
 print "{";
 
+for (i = 0; i < n_extra_target_vars; i++) {
+	print "  opts->x_" extra_target_vars[i] " = ptr->x_" extra_target_vars[i] ";";
+}
+
 for (i = 0; i < n_target_other; i++) {
 	print "  opts->x_" var_target_other[i] " = ptr->x_" var_target_other[i] ";";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  opts->x_" var_target_enum[i] " = ptr->x_" var_target_enum[i] ";";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  opts->x_" var_target_int[i] " = ptr->x_" var_target_int[i] ";";
 }
@@ -565,6 +643,15 @@ for (i = 0; i < n_target_other; i++) {
 	print "";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  if (ptr->x_" var_target_enum[i] ")";
+	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
+	print "             indent, \"\",";
+	print "             \"" var_target_enum[i] "\",";
+	print "             ptr->x_" var_target_enum[i] ");";
+	print "";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  if (ptr->x_" var_target_int[i] ")";
 	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
Index: gcc/opth-gen.awk
===================================================================
--- gcc/opth-gen.awk	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/opth-gen.awk	(working copy)
@@ -29,7 +29,12 @@ BEGIN {
 	n_langs = 0
 	n_target_save = 0
 	n_extra_vars = 0
+	n_extra_target_vars = 0
 	n_extra_masks = 0
+	n_extra_c_includes = 0
+	n_extra_h_includes = 0
+	have_save = 0;
+	quote = "\042"
 	FS=SUBSEP
 }
 
@@ -48,6 +53,30 @@ BEGIN {
 			extra_vars[n_extra_vars] = $2
 			n_extra_vars++
 		}
+		else if ($1 == "TargetVariable") {
+			# Combination of TargetSave and Variable
+			extra_vars[n_extra_vars] = $2
+			n_extra_vars++
+
+			var = $2
+			sub(" *=.*", "", var)
+			orig_var = var
+			name = var
+			type = var
+			sub("^.*[ *]", "", name)
+			sub(" *" name "$", "", type)
+			target_save_decl[n_target_save] = type " x_" name
+			n_target_save++
+
+			extra_target_vars[n_extra_target_vars] = name
+			n_extra_target_vars++
+		}
+		else if ($1 == "HeaderInclude") {
+			extra_h_includes[n_extra_h_includes++] = $2;
+		}
+		else if ($1 == "SourceInclude")  {
+			extra_c_includes[n_extra_c_includes++] = $2;
+		}
 		else {
 			name = opt_args("Mask", $1)
 			if (name == "") {
@@ -73,11 +102,21 @@ print ""
 print "#include \"flag-types.h\""
 print ""
 
-have_save = 0;
+if (n_extra_h_includes > 0) {
+	for (i = 0; i < n_extra_h_includes; i++) {
+		print "#include " quote extra_h_includes[i] quote
+	}
+	print ""
+}
 
 print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
 print "#ifndef GENERATOR_FILE"
-print "struct gcc_options\n{"
+print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
+print "struct GTY(()) gcc_options"
+print "#else"
+print "struct gcc_options"
+print "#endif"
+print "{"
 print "#endif"
 
 for (i = 0; i < n_extra_vars; i++) {
@@ -151,6 +190,7 @@ print "{";
 n_opt_char = 2;
 n_opt_short = 0;
 n_opt_int = 0;
+n_opt_enum = 0;
 n_opt_other = 0;
 var_opt_char[0] = "unsigned char x_optimize";
 var_opt_char[1] = "unsigned char x_optimize_size";
@@ -175,6 +215,9 @@ for (i = 0; i < n_opts; i++) {
 		else if (otype ~ "^((un)?signed +)?char *$")
 			var_opt_char[n_opt_char++] = otype "x_" name;
 
+		else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+			var_opt_enum[n_opt_enum++] = otype "x_" name;
+
 		else
 			var_opt_other[n_opt_other++] = otype "x_" name;
 	}
@@ -184,6 +227,10 @@ for (i = 0; i < n_opt_other; i++) {
 	print "  " var_opt_other[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  " var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_int; i++) {
 	print "  " var_opt_int[i] ";";
 }
@@ -207,6 +254,7 @@ print "{";
 n_target_char = 0;
 n_target_short = 0;
 n_target_int = 0;
+n_target_enum = 0;
 n_target_other = 0;
 
 for (i = 0; i < n_target_save; i++) {
@@ -219,6 +267,9 @@ for (i = 0; i < n_target_save; i++) {
 	else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_ " alnum "]+$")
 		var_target_char[n_target_char++] = target_save_decl[i];
 
+	else if (target_save_decl[i] ~ ("^enum +[_" alnum "]+ +[_" alnum "]+$")) {
+		var_target_enum[n_target_enum++] = target_save_decl[i];
+	}
 	else
 		var_target_other[n_target_other++] = target_save_decl[i];
 }
@@ -244,6 +295,9 @@ if (have_save) {
 			else if (otype ~ "^((un)?signed +)?char *$")
 				var_target_char[n_target_char++] = otype "x_" name;
 
+			else if (otype ~ ("^enum +[_" alnum "]+ +[_" alnum "]+"))
+				var_target_enum[n_target_enum++] = otype "x_" name;
+
 			else
 				var_target_other[n_target_other++] = otype "x_" name;
 		}
@@ -256,6 +310,10 @@ for (i = 0; i < n_target_other; i++) {
 	print "  " var_target_other[i] ";";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  " var_target_enum[i] ";";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  " var_target_int[i] ";";
 }
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/Makefile.in	(working copy)
@@ -812,6 +812,16 @@ T_TARGET : $(T_TARGET)
 # at build time.
 SPECS = specs
 
+# Extra include files that are defined by HeaderInclude directives in
+# the .opt files
+OPTIONS_H_EXTRA =
+
+# Extra include files that are defined by SourceInclude directives in
+# the .opt files
+OPTIONS_C_EXTRA =
+
+@option_includes@
+
 # End of variables for you to override.
 
 # GTM_H lists the config files that the generator files depend on,
@@ -899,7 +909,7 @@ RECOG_H = recog.h
 ALIAS_H = alias.h coretypes.h
 EMIT_RTL_H = emit-rtl.h
 FLAGS_H = flags.h coretypes.h flag-types.h $(OPTIONS_H)
-OPTIONS_H = options.h flag-types.h
+OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
 FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H) vecprim.h $(TM_H)
 EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
 OPTABS_H = optabs.h insn-codes.h
@@ -2238,9 +2248,10 @@ s-options-h: optionlist $(srcdir)/opt-fu
 	$(STAMP) $@
 
 options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(FLAGS_H) \
-	$(TM_H) opts.h intl.h
+	$(TM_H) opts.h intl.h $(OPTIONS_C_EXTRA)
 
-gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
+gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h \
+	$(OPTIONS_C_EXTRA)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) \
 		-DGCC_DRIVER options.c
 
@@ -2818,7 +2829,7 @@ opts.o : opts.c opts.h $(OPTIONS_H) $(TO
    output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
    $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h \
    $(PLUGIN_H) $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
-opts-common.o : opts-common.c opts.h $(FLAGS_H) $(CONFIG_H) $(SYSTEM_H) \
+opts-common.o : opts-common.c opts.h $(FLAGS_H) $(OPTIONS_H) $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h intl.h $(DIAGNOSTIC_H) $(TM_H)
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
    $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \

-------------- next part --------------
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/doc/extend.texi	(working copy)
@@ -3258,6 +3258,8 @@ int core2_func (void) __attribute__ ((__
 int sse3_func (void) __attribute__ ((__target__ ("sse3")));
 @end smallexample
 
+@table @samp
+@item i386 target attributes
 On the 386, the following options are allowed:
 
 @table @samp
@@ -3400,19 +3402,190 @@ Specify which floating point unit to use
 @code{target("fpmath=sse,387")} option must be specified as
 @code{target("fpmath=sse+387")} because the comma would separate
 different options.
-@end table
 
-On the 386, you can use either multiple strings to specify multiple
-options, or you can separate the option with a comma (@code{,}).
+@item PowerPC target attributes
+On the PowerPC, the following options are allowed:
+
+@table @samp
+@item altivec
+@itemx no-altivec
+@cindex @code{target("altivec")} attribute
+Generate code that uses (does not use) AltiVec instructions.
+
+@item cmpb
+@itemx no-cmpb
+@cindex @code{target("cmpb")} attribute
+Generate code that uses (does not use) the compare bytes instruction
+implemented on the POWER6 processor and other processors that support
+the PowerPC V2.05 architecture.
+
+@item dlmzb
+@itemx no-dlmzb
+@cindex @code{target("dlmzb")} attribute
+Generate code that uses (does not use) the string-search @samp{dlmzb}
+instruction on the IBM 405, 440, 464 and 476 processors.  This instruction is
+generated by default when targetting those processors.
+
+@item fprnd
+@itemx no-fprnd
+@cindex @code{target("fprnd")} attribute
+Generate code that uses (does not use) the FP round to integer
+instructions implemented on the POWER5+ processor and other processors
+that support the PowerPC V2.03 architecture.
+
+@item hard-dfp
+@itemx no-hard-dfp
+@cindex @code{target("hard-dfp")} attribute
+Generate code that uses (does not use) the decimal floating point
+instructions implemented on some POWER processors.
+
+@item isel
+@itemx no-isel
+@cindex @code{target("isel")} attribute
+Generate code that uses (does not use) ISEL instruction.
+
+@item mfcrf
+@itemx no-mfcrf
+@cindex @code{target("mfcrf")} attribute
+Generate code that uses (does not use) the move from condition
+register field instruction implemented on the POWER4 processor and
+other processors that support the PowerPC V2.01 architecture.
+
+@item mfpgpr
+@itemx no-mfpgpr
+@cindex @code{target("mfpgpr")} attribute
+Generate code that uses (does not use) the FP move to/from general
+purpose register instructions implemented on the POWER6X processor and
+other processors that support the extended PowerPC V2.05 architecture.
+
+@item mulhw
+@itemx no-mulhw
+@cindex @code{target("mulhw")} attribute
+Generate code that uses (does not use) the half-word multiply and
+multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors.
+These instructions are generated by default when targetting those
+processors.
+
+@item multiple
+@itemx no-multiple
+@cindex @code{target("multiple")} attribute
+Generate code that uses (does not use) the load multiple word
+instructions and the store multiple word instructions.
+
+@item update
+@itemx no-update
+@cindex @code{target("update")} attribute
+Generate code that uses (does not use) the load or store instructions
+that update the base register to the address of the calculated memory
+location.
+
+@item popcntb
+@itemx no-popcntb
+@cindex @code{target("popcntb")} attribute
+Generate code that uses (does not use) the popcount and double
+precision FP reciprocal estimate instruction implemented on the POWER5
+processor and other processors that support the PowerPC V2.02
+architecture.
+
+@item popcntd
+@itemx no-popcntd
+@cindex @code{target("popcntd")} attribute
+Generate code that uses (does not use) the popcount instruction
+implemented on the POWER7 processor and other processors that support
+the PowerPC V2.06 architecture.
+
+@item powerpc-gfxopt
+@itemx no-powerpc-gfxopt
+@cindex @code{target("powerpc-gfxopt")} attribute
+Generate code that uses (does not use) the optional PowerPC
+architecture instructions in the Graphics group, including
+floating-point select.
+
+@item powerpc-gpopt
+@itemx no-powerpc-gpopt
+@cindex @code{target("powerpc-gpopt")} attribute
+Generate code that uses (does not use) the optional PowerPC
+architecture instructions in the General Purpose group, including
+floating-point square root.
+
+@item recip-precision
+@itemx no-recip-precision
+@cindex @code{target("recip-precision")} attribute
+Assume (do not assume) that the reciprocal estimate instructions
+provide higher precision estimates than is mandated by the powerpc
+ABI.
+
+@item string
+@itemx no-string
+@cindex @code{target("string")} attribute
+Generate code that uses (does not use) the load string instructions
+and the store string word instructions to save multiple registers and
+do small block moves.
+
+@item vsx
+@itemx no-vsx
+@cindex @code{target("vsx")} attribute
+Generate code that uses (does not use) vector/scalar (VSX)
+instructions, and also enable the use of built-in functions that allow
+more direct access to the VSX instruction set.
+
+@item friz
+@itemx no-friz
+@cindex @code{target("friz")} attribute
+Generate (do not generate) the @code{friz} instruction when the
+@option{-funsafe-math-optimizations} option is used to optimize
+rounding a floating point value to 64-bit integer and back to floating
+point.  The @code{friz} instruction does not return the same value if
+the floating point number is too large to fit in an integer.
+
+@item avoid-indexed-addresses
+@itemx no-avoid-indexed-addresses
+@cindex @code{target("avoid-indexed-addresses")} attribute
+Generate code that tries to avoid (not avoid) the use of indexed load
+or store instructions.
+
+@item fused-madd
+@itemx no-fused-madd
+@cindex @code{target("fused-madd")} attribute
+Generate code that uses (does not use) the floating point multiply and
+accumulate instructions.
+
+@item paired
+@itemx no-paired
+@cindex @code{target("paired")} attribute
+Generate code that uses (does not use) the generation of PAIRED simd
+instructions.
+
+@item longcall
+@itemx no-longcall
+@cindex @code{target("longcall")} attribute
+Generate code that assumes (does not assume) that all calls are far
+away so that a longer more expensive calling sequence is required.
+
+@item cpu=@var{CPU}
+@cindex @code{target("cpu=@var{CPU}")} attribute
+Specify the architecture to generate code for in compiling the function.
+
+@item tune=@var{TUNE}
+@cindex @code{target("tune=@var{TUNE}")} attribute
+Specify the architecture to tune for in compiling the function.
+@end table
+@end table
+@end table
 
-On the 386, the inliner will not inline a function that has different
-target options than the caller, unless the callee has a subset of the
-target options of the caller.  For example a function declared with
-@code{target("sse3")} can inline a function with
-@code{target("sse2")}, since @code{-msse3} implies @code{-msse2}.
+On the 386/x86_64 and PowerPC backends, you can use either multiple
+strings to specify multiple options, or you can separate the option
+with a comma (@code{,}).
+
+On the 386/x86_64 and PowerPC backends, the inliner will not inline a
+function that has different target options than the caller, unless the
+callee has a subset of the target options of the caller.  For example
+a function declared with @code{target("sse3")} can inline a function
+with @code{target("sse2")}, since @code{-msse3} implies @code{-msse2}.
 
 The @code{target} attribute is not implemented in GCC versions earlier
-than 4.4, and at present only the 386 uses it.
+than 4.4 for the i386/x86_64 and 4.6 for the PowerPC backends.  It is
+not currently implemented for other backends.
 
 @item tiny_data
 @cindex tiny data section on the H8/300H and H8S
@@ -12954,9 +13127,9 @@ function.  The parenthesis around the op
 @xref{Function Attributes}, for more information about the
 @code{target} attribute and the attribute syntax.
 
-The @samp{#pragma GCC target} pragma is not implemented in GCC
-versions earlier than 4.4, and is currently only implemented for the
-386 and x86_64 backends.
+The @code{#pragma GCC target} attribute is not implemented in GCC versions earlier
+than 4.4 for the i386/x86_64 and 4.6 for the PowerPC backends.  At
+present, it is not implemented for other backends.
 @end table
 
 @table @code
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/doc/invoke.texi	(working copy)
@@ -15609,7 +15609,7 @@ is enabled by default when targetting Po
 @opindex mno-fused-madd
 Generate code that uses (does not use) the floating point multiply and
 accumulate instructions.  These instructions are generated by default if
-hardware floating is used.
+hardware floating point is used.
 
 @item -mmulhw
 @itemx -mno-mulhw
Index: gcc/config/rs6000/aix.opt
===================================================================
--- gcc/config/rs6000/aix.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/aix.opt	(working copy)
@@ -20,5 +20,5 @@
 ; <http://www.gnu.org/licenses/>.
 
 mxl-compat
-Target Var(has_xl_compat_option)
+Target Var(has_xl_compat_option) Save
 Conform more closely to IBM XLC semantics
Index: gcc/config/rs6000/linux64.opt
===================================================================
--- gcc/config/rs6000/linux64.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/linux64.opt	(working copy)
@@ -20,7 +20,7 @@
 ; <http://www.gnu.org/licenses/>.
 
 mprofile-kernel
-Target Report Var(profile_kernel)
+Target Report Var(profile_kernel) Save
 Call mcount for profiling before a function prologue
 
 mcmodel=
Index: gcc/config/rs6000/sysv4.opt
===================================================================
--- gcc/config/rs6000/sysv4.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/sysv4.opt	(working copy)
@@ -32,7 +32,7 @@ Target RejectNegative Joined
 Specify bit size of immediate TLS offsets
 
 mbit-align
-Target Report Var(TARGET_NO_BITFIELD_TYPE)
+Target Report Var(TARGET_NO_BITFIELD_TYPE) Save
 Align to the base type of the bit-field
 
 mstrict-align
@@ -74,7 +74,7 @@ Target RejectNegative
 no description yet
 
 mprototype
-Target Var(target_prototype)
+Target Var(target_prototype) Save
 Assume all variable arg functions are prototyped
 
 ;; FIXME: Does nothing.
@@ -87,11 +87,11 @@ Target Report Mask(EABI)
 Use EABI
 
 mbit-word
-Target Report Var(TARGET_NO_BITFIELD_WORD)
+Target Report Var(TARGET_NO_BITFIELD_WORD) Save
 Allow bit-fields to cross word boundaries
 
 mregnames
-Target Var(rs6000_regnames)
+Target Var(rs6000_regnames) Save
 Use alternate register names
 
 ;; This option does nothing and only exists because the compiler
@@ -137,9 +137,9 @@ Target RejectNegative
 no description yet
 
 msecure-plt
-Target Report RejectNegative Var(secure_plt, 1)
+Target Report RejectNegative Var(secure_plt, 1) Save
 Generate code to use a non-exec PLT and GOT
 
 mbss-plt
-Target Report RejectNegative Var(secure_plt, 0)
+Target Report RejectNegative Var(secure_plt, 0) Save
 Generate code for old exec BSS PLT
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -176,6 +176,9 @@ extern void rs6000_aix_asm_output_dwarf_
 
 extern void rs6000_pragma_longcall (struct cpp_reader *);
 extern void rs6000_cpu_cpp_builtins (struct cpp_reader *);
+#ifdef TREE_CODE
+extern bool rs6000_pragma_target_parse (tree, tree);
+#endif
 
 #if TARGET_MACHO
 char *output_call (rtx, rtx *, int, int);
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -20,6 +20,105 @@
 ; along with GCC; see the file COPYING3.  If not see
 ; <http://www.gnu.org/licenses/>.
 
+HeaderInclude
+config/rs6000/rs6000-opts.h
+
+;; Current processor
+TargetVariable
+enum processor_type rs6000_cpu = PROCESSOR_RIOS1
+
+;; Always emit branch hint bits.
+TargetVariable
+unsigned char rs6000_always_hint
+
+;; Schedule instructions for group formation.
+TargetVariable
+unsigned char rs6000_sched_groups
+
+;; Align branch targets.
+TargetVariable
+unsigned char rs6000_align_branch_targets
+
+;; Support for -msched-costly-dep option.
+TargetVariable
+enum rs6000_dependence_cost rs6000_sched_costly_dep = no_dep_costly
+
+;; Support for -minsert-sched-nops option.
+TargetVariable
+enum rs6000_nop_insertion rs6000_sched_insert_nops = sched_finish_none
+
+;; Size of long double.
+TargetVariable
+unsigned char rs6000_long_double_type_size
+
+;; IEEE quad extended precision long double.
+TargetVariable
+unsigned char rs6000_ieeequad
+
+;; Nonzero to use AltiVec ABI.
+TargetVariable
+unsigned char rs6000_altivec_abi
+
+;; Nonzero if we want SPE SIMD instructions.
+TargetVariable
+int rs6000_spe
+
+;; Nonzero if we want SPE ABI extensions.
+TargetVariable
+unsigned char rs6000_spe_abi
+
+;; Nonzero if floating point operations are done in the GPRs.
+TargetVariable
+unsigned char rs6000_float_gprs
+
+;; Nonzero if we want Darwin's struct-by-value-in-regs ABI.
+TargetVariable
+unsigned char rs6000_darwin64_abi
+
+;; Which small data model to use (for System V targets only)
+TargetVariable
+enum rs6000_sdata_type rs6000_sdata = SDATA_DATA
+
+;; Bit size of immediate TLS offsets and string from which it is decoded.
+TargetVariable
+int rs6000_tls_size = 32
+
+;; ABI enumeration available for subtarget to use.
+TargetVariable
+enum rs6000_abi rs6000_current_abi = ABI_NONE
+
+;; Type of traceback to use.
+TargetVariable
+enum rs6000_traceback_type rs6000_traceback = traceback_default
+
+;; Control alignment for fields within structures.
+TargetVariable
+unsigned char rs6000_alignment_flags
+
+;; Code model for 64-bit linux.
+TargetVariable
+enum rs6000_cmodel rs6000_current_cmodel = CMODEL_SMALL
+
+;; What type of reciprocal estimation instructions to generate
+TargetVariable
+unsigned int rs6000_recip_control
+
+;; -mcpu=<xxx> as an index into the processor_target_table or -1
+TargetVariable
+int rs6000_cpu_index = -1
+
+;; -mtune=<xxx> as an index into the processor_target_table or -1
+TargetVariable
+int rs6000_tune_index = -1
+
+;; Debug flags
+TargetVariable
+unsigned int rs6000_debug
+
+;; Save for target_flags_explicit
+TargetSave
+int rs6000_target_flags_explicit
+
 mpower
 Target Report RejectNegative Mask(POWER)
 Use POWER instruction set
@@ -45,55 +144,55 @@ Target Report Mask(POWERPC64)
 Use PowerPC-64 instruction set
 
 mpowerpc-gpopt
-Target Report Mask(PPC_GPOPT)
+Target Report Mask(PPC_GPOPT) Save
 Use PowerPC General Purpose group optional instructions
 
 mpowerpc-gfxopt
-Target Report Mask(PPC_GFXOPT)
+Target Report Mask(PPC_GFXOPT) Save
 Use PowerPC Graphics group optional instructions
 
 mmfcrf
-Target Report Mask(MFCRF)
+Target Report Mask(MFCRF) Save
 Use PowerPC V2.01 single field mfcr instruction
 
 mpopcntb
-Target Report Mask(POPCNTB)
+Target Report Mask(POPCNTB) Save
 Use PowerPC V2.02 popcntb instruction
 
 mfprnd
-Target Report Mask(FPRND)
+Target Report Mask(FPRND) Save
 Use PowerPC V2.02 floating point rounding instructions
 
 mcmpb
-Target Report Mask(CMPB)
+Target Report Mask(CMPB) Save
 Use PowerPC V2.05 compare bytes instruction
 
 mmfpgpr
-Target Report Mask(MFPGPR)
+Target Report Mask(MFPGPR) Save
 Use extended PowerPC V2.05 move floating point to/from GPR instructions
 
 maltivec
-Target Report Mask(ALTIVEC)
+Target Report Mask(ALTIVEC) Save
 Use AltiVec instructions
 
 mhard-dfp
-Target Report Mask(DFP)
+Target Report Mask(DFP) Save
 Use decimal floating point instructions
 
 mmulhw
-Target Report Mask(MULHW)
+Target Report Mask(MULHW) Save
 Use 4xx half-word multiply instructions
 
 mdlmzb
-Target Report Mask(DLMZB)
+Target Report Mask(DLMZB) Save
 Use 4xx string-search dlmzb instruction
 
 mmultiple
-Target Report Mask(MULTIPLE)
+Target Report Mask(MULTIPLE) Save
 Generate load/store multiple instructions
 
 mstring
-Target Report Mask(STRING)
+Target Report Mask(STRING) Save
 Generate string instructions for block moves
 
 mnew-mnemonics
@@ -113,11 +212,11 @@ Target Report RejectNegative InverseMask
 Use hardware floating point
 
 mpopcntd
-Target Report Mask(POPCNTD)
+Target Report Mask(POPCNTD) Save
 Use PowerPC V2.06 popcntd instruction
 
 mfriz
-Target Report Var(TARGET_FRIZ) Init(-1)
+Target Report Var(TARGET_FRIZ) Init(-1) Save
 Under -ffast-math, generate a FRIZ instruction for (double)(long long) conversions
 
 mveclibabi=
@@ -125,7 +224,7 @@ Target RejectNegative Joined Var(rs6000_
 Vector library ABI to use
 
 mvsx
-Target Report Mask(VSX)
+Target Report Mask(VSX) Save
 Use vector/scalar (VSX) instructions
 
 mvsx-scalar-double
@@ -165,7 +264,7 @@ Target Undocumented Report Var(TARGET_VE
 ; Explicitly control whether we vectorize the builtins or not.
 
 mno-update
-Target Report RejectNegative Mask(NO_UPDATE)
+Target Report RejectNegative Mask(NO_UPDATE) Save
 Do not generate load/store with update instructions
 
 mupdate
@@ -173,34 +272,34 @@ Target Report RejectNegative InverseMask
 Generate load/store with update instructions
 
 mavoid-indexed-addresses
-Target Report Var(TARGET_AVOID_XFORM) Init(-1)
+Target Report Var(TARGET_AVOID_XFORM) Init(-1) Save
 Avoid generation of indexed load/store instructions when possible
 
 mfused-madd
-Target Report Var(TARGET_FUSED_MADD) Init(1)
+Target Report Var(TARGET_FUSED_MADD) Init(1) Save
 Generate fused multiply/add instructions
 
 mtls-markers
-Target Report Var(tls_markers) Init(1)
+Target Report Var(tls_markers) Init(1) Save
 Mark __tls_get_addr calls with argument info
 
 msched-epilog
 Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1)
 
 msched-prolog
-Target Report Var(TARGET_SCHED_PROLOG)
+Target Report Var(TARGET_SCHED_PROLOG) Save
 Schedule the start and end of the procedure
 
 maix-struct-return
-Target Report RejectNegative Var(aix_struct_return)
+Target Report RejectNegative Var(aix_struct_return) Save
 Return all structures in memory (AIX default)
 
 msvr4-struct-return
-Target Report RejectNegative Var(aix_struct_return,0)
+Target Report RejectNegative Var(aix_struct_return,0) Save
 Return small structures in registers (SVR4 default)
 
 mxl-compat
-Target Report Var(TARGET_XL_COMPAT)
+Target Report Var(TARGET_XL_COMPAT) Save
 Conform more closely to IBM XLC semantics
 
 mrecip
@@ -212,23 +311,23 @@ Target Report RejectNegative Joined
 Generate software reciprocal divide and square root for better throughput.
 
 mrecip-precision
-Target Report Mask(RECIP_PRECISION)
+Target Report Mask(RECIP_PRECISION) Save
 Assume that the reciprocal estimate instructions provide more accuracy.
 
 mno-fp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC)
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC) Save
 Do not place floating point constants in TOC
 
 mfp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0)
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0) Save
 Place floating point constants in TOC
 
 mno-sum-in-toc
-Target RejectNegative Var(TARGET_NO_SUM_IN_TOC)
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC) Save
 Do not place symbol+offset constants in TOC
 
 msum-in-toc
-Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0)
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0) Save
 Place symbol+offset constants in TOC
 
 ;  Output only one TOC entry per module.  Normally linking fails if
@@ -247,7 +346,7 @@ Target Report
 Put everything in the regular TOC
 
 mvrsave
-Target Report Var(TARGET_ALTIVEC_VRSAVE)
+Target Report Var(TARGET_ALTIVEC_VRSAVE) Save
 Generate VRSAVE instructions when generating AltiVec code
 
 mvrsave=
@@ -255,11 +354,11 @@ Target RejectNegative Joined
 -mvrsave=yes/no	Deprecated option.  Use -mvrsave/-mno-vrsave instead
 
 mblock-move-inline-limit=
-Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger
+Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger Save
 Specify how many bytes should be moved inline before calling out to memcpy/memmove
 
 misel
-Target Report Mask(ISEL)
+Target Report Mask(ISEL) Save
 Generate isel instructions
 
 misel=
@@ -271,7 +370,7 @@ Target
 Generate SPE SIMD instructions on E500
 
 mpaired
-Target Var(rs6000_paired_float)
+Target Var(rs6000_paired_float) Save
 Generate PPC750CL paired-single instructions
 
 mspe=
@@ -299,19 +398,19 @@ Target RejectNegative Joined
 -mtraceback=	Select full, part, or no traceback table
 
 mlongcall
-Target Report Var(rs6000_default_long_calls)
+Target Report Var(rs6000_default_long_calls) Save
 Avoid all range limits on call instructions
 
 mgen-cell-microcode
-Target Report Var(rs6000_gen_cell_microcode) Init(-1)
+Target Report Var(rs6000_gen_cell_microcode) Init(-1) Save
 Generate Cell microcode
 
 mwarn-cell-microcode
-Target Var(rs6000_warn_cell_microcode) Init(0) Warning
+Target Var(rs6000_warn_cell_microcode) Init(0) Warning Save
 Warn when a Cell microcoded instruction is emitted
 
 mwarn-altivec-long
-Target Var(rs6000_warn_altivec_long) Init(1)
+Target Var(rs6000_warn_altivec_long) Init(1) Save
 Warn about deprecated 'vector long ...' AltiVec type usage
 
 mfloat-gprs=
@@ -335,19 +434,19 @@ Target RejectNegative Joined
 Specify alignment of structure fields default/natural
 
 mprioritize-restricted-insns=
-Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority)
+Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority) Save
 Specify scheduling priority for dispatch slot restricted insns
 
 msingle-float
-Target RejectNegative Var(rs6000_single_float)
+Target RejectNegative Var(rs6000_single_float) Save
 Single-precision floating point unit
 
 mdouble-float
-Target RejectNegative Var(rs6000_double_float)
+Target RejectNegative Var(rs6000_double_float) Save
 Double-precision floating point unit
 
 msimple-fpu
-Target RejectNegative Var(rs6000_simple_fpu)
+Target RejectNegative Var(rs6000_simple_fpu) Save
 Floating point unit does not support divide & sqrt
 
 mfpu=
@@ -355,7 +454,7 @@ Target RejectNegative Joined 
 -mfpu=	Specify FP (sp, dp, sp-lite, dp-lite) (implies -mxilinx-fpu)
 
 mxilinx-fpu
-Target Var(rs6000_xilinx_fpu)
+Target Var(rs6000_xilinx_fpu) Save
 Specify Xilinx FPU.
 
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -136,7 +136,6 @@ typedef struct GTY(()) machine_function
 
 /* Target cpu type */
 
-enum processor_type rs6000_cpu;
 struct rs6000_cpu_select rs6000_select[3] =
 {
   /* switch		name,			tune	arch */
@@ -145,47 +144,19 @@ struct rs6000_cpu_select rs6000_select[3
   { (const char *)0,	"-mtune=",		1,	0 },
 };
 
-/* Always emit branch hint bits.  */
-static GTY(()) bool rs6000_always_hint;
-
-/* Schedule instructions for group formation.  */
-static GTY(()) bool rs6000_sched_groups;
-
-/* Align branch targets.  */
-static GTY(()) bool rs6000_align_branch_targets;
+/* String variables to hold the various options.  */
+static const char *rs6000_sched_insert_nops_str;
+static const char *rs6000_sched_costly_dep_str;
+static const char *rs6000_recip_name;
 
-/* Support for -msched-costly-dep option.  */
-const char *rs6000_sched_costly_dep_str;
-enum rs6000_dependence_cost rs6000_sched_costly_dep;
-
-/* Support for -minsert-sched-nops option.  */
-const char *rs6000_sched_insert_nops_str;
-enum rs6000_nop_insertion rs6000_sched_insert_nops;
+#ifdef USING_ELFOS_H
+static const char *rs6000_abi_name;
+static const char *rs6000_sdata_name;
+#endif
 
 /* Support targetm.vectorize.builtin_mask_for_load.  */
 static GTY(()) tree altivec_builtin_mask_for_load;
 
-/* Size of long double.  */
-int rs6000_long_double_type_size;
-
-/* IEEE quad extended precision long double. */
-int rs6000_ieeequad;
-
-/* Nonzero to use AltiVec ABI.  */
-int rs6000_altivec_abi;
-
-/* Nonzero if we want SPE SIMD instructions.  */
-int rs6000_spe;
-
-/* Nonzero if we want SPE ABI extensions.  */
-int rs6000_spe_abi;
-
-/* Nonzero if floating point operations are done in the GPRs.  */
-int rs6000_float_gprs = 0;
-
-/* Nonzero if we want Darwin's struct-by-value-in-regs ABI.  */
-int rs6000_darwin64_abi;
-
 /* Set to nonzero once AIX common-mode calls have been defined.  */
 static GTY(()) int common_mode_defined;
 
@@ -194,37 +165,13 @@ static GTY(()) int common_mode_defined;
 int rs6000_pic_labelno;
 
 #ifdef USING_ELFOS_H
-/* Which abi to adhere to */
-const char *rs6000_abi_name;
-
-/* Semantics of the small data area */
-enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;
-
-/* Which small data model to use */
-const char *rs6000_sdata_name = (char *)0;
-
 /* Counter for labels which are to be placed in .fixup.  */
 int fixuplabelno = 0;
 #endif
 
-/* Bit size of immediate TLS offsets and string from which it is decoded.  */
-int rs6000_tls_size = 32;
-const char *rs6000_tls_size_string;
-
-/* ABI enumeration available for subtarget to use.  */
-enum rs6000_abi rs6000_current_abi;
-
 /* Whether to use variant of AIX ABI for PowerPC64 Linux.  */
 int dot_symbols;
 
-/* Debug flags */
-const char *rs6000_debug_name;
-int rs6000_debug_stack;		/* debug stack applications */
-int rs6000_debug_arg;		/* debug argument handling */
-int rs6000_debug_reg;		/* debug register classes */
-int rs6000_debug_addr;		/* debug memory addressing */
-int rs6000_debug_cost;		/* debug rtx_costs */
-
 /* Specify the machine mode that pointers have.  After generation of rtl, the
    compiler makes no further distinction between pointers and any other objects
    of this machine mode.  The type is unsigned since not all things that
@@ -254,14 +201,6 @@ static enum insn_code rs6000_vector_relo
 tree rs6000_builtin_types[RS6000_BTI_MAX];
 tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
 
-const char *rs6000_traceback_name;
-static enum {
-  traceback_default = 0,
-  traceback_none,
-  traceback_part,
-  traceback_full
-} rs6000_traceback;
-
 /* Flag to say the TOC is initialized */
 int toc_initialized;
 char toc_label_name[10];
@@ -276,13 +215,6 @@ static GTY(()) section *read_only_privat
 static GTY(()) section *sdata2_section;
 static GTY(()) section *toc_section;
 
-/* Control alignment for fields within structures.  */
-/* String from -malign-XXXXX.  */
-int rs6000_alignment_flags;
-
-/* Code model for 64-bit linux.  */
-enum rs6000_cmodel cmodel;
-
 /* True for any options that were explicitly set.  */
 static struct {
   bool aix_struct_ret;		/* True if -maix-struct-ret was used.  */
@@ -352,9 +284,6 @@ enum rs6000_recip_mask {
   RECIP_LOW_PRECISION	= (RECIP_ALL & ~(RECIP_DF_RSQRT | RECIP_V2DF_RSQRT))
 };
 
-static unsigned int rs6000_recip_control;
-static const char *rs6000_recip_name;
-
 /* -mrecip options.  */
 static struct
 {
@@ -1139,7 +1068,6 @@ static void rs6000_option_override (void
 static void rs6000_option_init_struct (struct gcc_options *);
 static void rs6000_option_default_params (void);
 static bool rs6000_handle_option (size_t, const char *, int);
-static void rs6000_parse_tls_size_option (void);
 static void rs6000_parse_yes_no_option (const char *, const char *, int *);
 static int first_altivec_reg_to_save (void);
 static unsigned int compute_vrsave_mask (void);
@@ -1294,6 +1222,15 @@ struct GTY(()) builtin_hash_struct
 };
 
 static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table;
+
+static bool rs6000_valid_attribute_p (tree, tree, tree, int);
+static void rs6000_function_specific_save (struct cl_target_option *);
+static void rs6000_function_specific_restore (struct cl_target_option *);
+static void rs6000_function_specific_print (FILE *, int,
+					    struct cl_target_option *);
+static bool rs6000_can_inline_p (tree, tree);
+static void rs6000_set_current_function (tree);
+
 
 /* Default register names.  */
 char rs6000_reg_names[][8] =
@@ -1689,8 +1626,212 @@ static const struct default_options rs60
 #undef TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE rs6000_function_value
 
+#undef TARGET_OPTION_VALID_ATTRIBUTE_P
+#define TARGET_OPTION_VALID_ATTRIBUTE_P rs6000_valid_attribute_p
+
+#undef TARGET_OPTION_SAVE
+#define TARGET_OPTION_SAVE rs6000_function_specific_save
+
+#undef TARGET_OPTION_RESTORE
+#define TARGET_OPTION_RESTORE rs6000_function_specific_restore
+
+#undef TARGET_OPTION_PRINT
+#define TARGET_OPTION_PRINT rs6000_function_specific_print
+
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P rs6000_can_inline_p
+
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION rs6000_set_current_function
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
+
+/* Simplifications for entries below.  */
+
+enum {
+  POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
+  POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC
+};
+
+/* Some OSs don't support saving the high part of 64-bit registers on context
+   switch.  Other OSs don't support saving Altivec registers.  On those OSs, we
+   don't touch the MASK_POWERPC64 or MASK_ALTIVEC settings; if the user wants
+   either, the user must explicitly specify them and we won't interfere with
+   the user's specification.  */
+
+enum {
+  POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
+  POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
+		   | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
+		   | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
+		   | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
+		   | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE
+		   | MASK_RECIP_PRECISION)
+};
+
+/* Masks for instructions set at various powerpc ISAs.  */
+enum {
+  ISA_2_1_MASKS = MASK_MFCRF,
+  ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB | MASK_FPRND),
+
+  /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't add
+     ALTIVEC, since in general it isn't a win on power6.  In ISA 2.04, fsel,
+     fre, fsqrt, etc. were no longer documented as optional.  Group masks by
+     server and embedded. */
+  ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION
+			    | MASK_PPC_GFXOPT | MASK_PPC_GPOPT),
+  ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP),
+
+  /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
+     altivec is a win so enable it.  */
+  ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD),
+  ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC
+			  | MASK_VSX)
+};
+
+/* This table occasionally claims that a processor does not support a
+   particular feature even though it does, but the feature is slower than the
+   alternative.  Thus, it shouldn't be relied on as a complete description of
+   the processor's support.
+
+   Please keep this list in order, and don't forget to update the documentation
+   in invoke.texi when adding a new processor or flag.  */
+
+struct rs6000_ptt
+{
+  const char *const name;		/* Canonical processor name.  */
+  const enum processor_type processor;	/* Processor type enum value.  */
+  const int target_enable;		/* Target flags to enable.  */
+};
+
+static struct rs6000_ptt const processor_target_table[] =
+{
+  {"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"403", PROCESSOR_PPC403,
+   POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
+  {"405", PROCESSOR_PPC405,
+   POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+  {"405fp", PROCESSOR_PPC405,
+   POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+  {"440", PROCESSOR_PPC440,
+   POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+  {"440fp", PROCESSOR_PPC440,
+   POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+  {"464", PROCESSOR_PPC440,
+   POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+  {"464fp", PROCESSOR_PPC440,
+   POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+  {"476", PROCESSOR_PPC476,
+   POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF
+   | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
+  {"476fp", PROCESSOR_PPC476,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB
+   | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
+  {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
+  {"601", PROCESSOR_PPC601,
+   MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
+  {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"620", PROCESSOR_PPC620,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+  {"630", PROCESSOR_PPC630,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+  {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK},
+  {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK},
+  {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
+   | MASK_ISEL},
+  /* 8548 has a dummy entry for now.  */
+  {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
+   | MASK_ISEL},
+  {"a2", PROCESSOR_PPCA2,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB
+   | MASK_CMPB | MASK_NO_UPDATE },
+  {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
+  {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
+   | MASK_ISEL},
+  {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
+   | MASK_PPC_GFXOPT | MASK_ISEL},
+  {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"970", PROCESSOR_POWER4,
+   POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+  {"cell", PROCESSOR_CELL,
+   POWERPC_7400_MASK  | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+  {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS},
+  {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+  {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+  {"G4",  PROCESSOR_PPC7450, POWERPC_7400_MASK},
+  {"G5", PROCESSOR_POWER4,
+   POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+  {"titan", PROCESSOR_TITAN,
+   POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+  {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+  {"power2", PROCESSOR_POWER,
+   MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
+  {"power3", PROCESSOR_PPC630,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+  {"power4", PROCESSOR_POWER4,
+   POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+   | MASK_MFCRF},
+  {"power5", PROCESSOR_POWER5,
+   POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+   | MASK_MFCRF | MASK_POPCNTB},
+  {"power5+", PROCESSOR_POWER5,
+   POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+   | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
+  {"power6", PROCESSOR_POWER6,
+   POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+   | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
+   | MASK_RECIP_PRECISION},
+  {"power6x", PROCESSOR_POWER6,
+   POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+   | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
+   | MASK_MFPGPR | MASK_RECIP_PRECISION},
+  {"power7", PROCESSOR_POWER7,   /* Don't add MASK_ISEL by default */
+   POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
+   | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
+   | MASK_VSX | MASK_RECIP_PRECISION},
+  {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
+  {"powerpc64", PROCESSOR_POWERPC64,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+  {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+  {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+  {"rios2", PROCESSOR_RIOS2,
+   MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
+  {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+  {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+  {"rs64", PROCESSOR_RS64A,
+   POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
+};
+
+/* Look up a processor name for -mcpu=xxx and -mtune=xxx.  Return -1 if the
+   name is invalid.  */
+
+static int
+rs6000_cpu_name_lookup (const char *name)
+{
+  size_t i;
+
+  if (name != NULL)
+    {
+      for (i = 0; i < ARRAY_SIZE (processor_target_table); i++)
+	if (! strcmp (name, processor_target_table[i].name))
+	  return (int)i;
+    }
+
+  return -1;
+}
+
+
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
    This is ordinarily the length in words of a value of mode MODE
@@ -2420,186 +2561,24 @@ darwin_rs6000_override_options (void)
 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
 #endif
 
-/* Override command line options.  Mostly we process the processor
-   type and sometimes adjust other TARGET_ options.  */
+/* Override command line options.  Mostly we process the processor type and
+   sometimes adjust other TARGET_ options.  */
 
-static void
-rs6000_option_override_internal (const char *default_cpu)
+static bool
+rs6000_option_override_internal (bool global_init_p)
 {
-  size_t i, j;
-  struct rs6000_cpu_select *ptr;
+  bool ret = true;
+  const char *default_cpu = OPTION_TARGET_CPU_DEFAULT;
   int set_masks;
-
-  /* Simplifications for entries below.  */
-
-  enum {
-    POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
-    POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC
-  };
-
-  /* This table occasionally claims that a processor does not support
-     a particular feature even though it does, but the feature is slower
-     than the alternative.  Thus, it shouldn't be relied on as a
-     complete description of the processor's support.
-
-     Please keep this list in order, and don't forget to update the
-     documentation in invoke.texi when adding a new processor or
-     flag.  */
-  static struct ptt
-    {
-      const char *const name;		/* Canonical processor name.  */
-      const enum processor_type processor; /* Processor type enum value.  */
-      const int target_enable;	/* Target flags to enable.  */
-    } const processor_target_table[]
-      = {{"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"403", PROCESSOR_PPC403,
-	  POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
-	 {"405", PROCESSOR_PPC405,
-	  POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
-	 {"405fp", PROCESSOR_PPC405,
-	  POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
-	 {"440", PROCESSOR_PPC440,
-	  POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
-	 {"440fp", PROCESSOR_PPC440,
-	  POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
-	 {"464", PROCESSOR_PPC440,
-	  POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
-	 {"464fp", PROCESSOR_PPC440,
-	  POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
- 	 {"476", PROCESSOR_PPC476,
-	  POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF
-	  | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
- 	 {"476fp", PROCESSOR_PPC476,
-	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB
-	  | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
-	 {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
-	 {"601", PROCESSOR_PPC601,
-	  MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
-	 {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"620", PROCESSOR_PPC620,
-	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
-	 {"630", PROCESSOR_PPC630,
-	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
-	 {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK},
-	 {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK},
-	 {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
-	  | MASK_ISEL},
-	 /* 8548 has a dummy entry for now.  */
-	 {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
-	  | MASK_ISEL},
- 	 {"a2", PROCESSOR_PPCA2,
- 	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB
- 	  | MASK_CMPB | MASK_NO_UPDATE },
-	 {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
-	 {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
-	  | MASK_ISEL},
-	 {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
-	  | MASK_PPC_GFXOPT | MASK_ISEL},
-	 {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"970", PROCESSOR_POWER4,
-	  POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
-	 {"cell", PROCESSOR_CELL,
-	  POWERPC_7400_MASK  | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
-	 {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS},
-	 {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-	 {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-	 {"G4",  PROCESSOR_PPC7450, POWERPC_7400_MASK},
-	 {"G5", PROCESSOR_POWER4,
-	  POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
-	 {"titan", PROCESSOR_TITAN,
-	  POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
-	 {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
-	 {"power2", PROCESSOR_POWER,
-	  MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
-	 {"power3", PROCESSOR_PPC630,
-	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
-	 {"power4", PROCESSOR_POWER4,
-	  POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
-	  | MASK_MFCRF},
-	 {"power5", PROCESSOR_POWER5,
-	  POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
-	  | MASK_MFCRF | MASK_POPCNTB},
-	 {"power5+", PROCESSOR_POWER5,
-	  POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
-	  | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
- 	 {"power6", PROCESSOR_POWER6,
-	  POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
-	  | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
-	  | MASK_RECIP_PRECISION},
-	 {"power6x", PROCESSOR_POWER6,
-	  POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
-	  | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
-	  | MASK_MFPGPR | MASK_RECIP_PRECISION},
-	 {"power7", PROCESSOR_POWER7,   /* Don't add MASK_ISEL by default */
-	  POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
-	  | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
-	  | MASK_VSX | MASK_RECIP_PRECISION},
-	 {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
-	 {"powerpc64", PROCESSOR_POWERPC64,
-	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
-	 {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
-	 {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
-	 {"rios2", PROCESSOR_RIOS2,
-	  MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
-	 {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
-	 {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
-	 {"rs64", PROCESSOR_RS64A,
-	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
-      };
-
-  const size_t ptt_size = ARRAY_SIZE (processor_target_table);
-
-  /* Some OSs don't support saving the high part of 64-bit registers on
-     context switch.  Other OSs don't support saving Altivec registers.
-     On those OSs, we don't touch the MASK_POWERPC64 or MASK_ALTIVEC
-     settings; if the user wants either, the user must explicitly specify
-     them and we won't interfere with the user's specification.  */
-
-  enum {
-    POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
-    POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
-		     | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
-		     | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
-		     | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
-		     | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE
-		     | MASK_RECIP_PRECISION)
-  };
-
-  /* Masks for instructions set at various powerpc ISAs.  */
-  enum {
-    ISA_2_1_MASKS = MASK_MFCRF,
-    ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB | MASK_FPRND),
-
-    /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't
-       add ALTIVEC, since in general it isn't a win on power6.  In ISA 2.04,
-       fsel, fre, fsqrt, etc. were no longer documented as optional.  Group
-       masks by server and embedded. */
-    ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION
-			      | MASK_PPC_GFXOPT | MASK_PPC_GPOPT),
-    ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP),
-
-    /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
-       altivec is a win so enable it.  */
-    ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD),
-    ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC
-			    | MASK_VSX)
-  };
+  int defcpu_index;
+  int cpu_index;
+  int tune_index;
 
   /* Numerous experiment shows that IRA based loop pressure
      calculation works better for RTL loop invariant motion on targets
      with enough (>= 32) registers.  It is an expensive optimization.
      So it is on only for peak performance.  */
-  if (optimize >= 3)
+  if (optimize >= 3 && global_init_p)
     flag_ira_loop_pressure = 1;
 
   /* Set the pointer size.  */
@@ -2628,41 +2607,44 @@ rs6000_option_override_internal (const c
   set_masks &= ~target_flags_explicit;
 
   /* Identify the processor type.  */
-  rs6000_select[0].string = default_cpu;
-  rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
-
-  for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
+  if (!default_cpu)
     {
-      ptr = &rs6000_select[i];
-      if (ptr->string != (char *)0 && ptr->string[0] != '\0')
-	{
-	  for (j = 0; j < ptt_size; j++)
-	    if (! strcmp (ptr->string, processor_target_table[j].name))
-	      {
-		if (ptr->set_tune_p)
-		  rs6000_cpu = processor_target_table[j].processor;
+      if (TARGET_POWERPC64)
+	default_cpu = "powerpc64";
+      else if (TARGET_POWERPC)
+	default_cpu = "powerpc";
+    }
 
-		if (ptr->set_arch_p)
-		  {
-		    target_flags &= ~set_masks;
-		    target_flags |= (processor_target_table[j].target_enable
-				     & set_masks);
-		  }
-		break;
-	      }
+  defcpu_index = rs6000_cpu_name_lookup (default_cpu);
+  cpu_index = (rs6000_cpu_index > 0) ? rs6000_cpu_index : defcpu_index;
+  tune_index = (rs6000_tune_index > 0) ? rs6000_tune_index : cpu_index;
 
-	  if (j == ptt_size)
-	    error ("bad value (%s) for %s switch", ptr->string, ptr->name);
-	}
+  if (cpu_index >= 0)
+    {
+      target_flags &= ~set_masks;
+      target_flags |= (processor_target_table[cpu_index].target_enable
+		       & set_masks);
     }
 
+  rs6000_cpu = ((tune_index >= 0)
+		? processor_target_table[tune_index].processor
+		: (TARGET_POWERPC64
+		   ? PROCESSOR_DEFAULT64
+		   : PROCESSOR_DEFAULT));
+
   if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
       || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
     {
       if (TARGET_ALTIVEC)
-	error ("AltiVec not supported in this target");
+	{
+	  error ("AltiVec not supported in this target");
+	  ret = false;
+	}
       if (TARGET_SPE)
-	error ("Spe not supported in this target");
+	{
+	  error ("Spe not supported in this target");
+	  ret = false;
+	}
     }
 
   /* Disable Cell microcode if we are optimizing for the Cell
@@ -2764,25 +2746,8 @@ rs6000_option_override_internal (const c
   if (rs6000_block_move_inline_limit < (TARGET_POWERPC64 ? 64 : 32))
     rs6000_block_move_inline_limit = (TARGET_POWERPC64 ? 64 : 32);
 
-  /* Set debug flags */
-  if (rs6000_debug_name)
+  if (global_init_p)
     {
-      if (! strcmp (rs6000_debug_name, "all"))
-	rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
-	  = rs6000_debug_addr = rs6000_debug_cost = 1;
-      else if (! strcmp (rs6000_debug_name, "stack"))
-	rs6000_debug_stack = 1;
-      else if (! strcmp (rs6000_debug_name, "arg"))
-	rs6000_debug_arg = 1;
-      else if (! strcmp (rs6000_debug_name, "reg"))
-	rs6000_debug_reg = 1;
-      else if (! strcmp (rs6000_debug_name, "addr"))
-	rs6000_debug_addr = 1;
-      else if (! strcmp (rs6000_debug_name, "cost"))
-	rs6000_debug_cost = 1;
-      else
-	error ("unknown -mdebug-%s switch", rs6000_debug_name);
-
       /* If the appropriate debug option is enabled, replace the target hooks
 	 with debug versions that call the real version and then prints
 	 debugging information.  */
@@ -2810,28 +2775,18 @@ rs6000_option_override_internal (const c
 	  rs6000_mode_dependent_address_ptr
 	    = rs6000_debug_mode_dependent_address;
 	}
-    }
 
-  if (rs6000_traceback_name)
-    {
-      if (! strncmp (rs6000_traceback_name, "full", 4))
-	rs6000_traceback = traceback_full;
-      else if (! strncmp (rs6000_traceback_name, "part", 4))
-	rs6000_traceback = traceback_part;
-      else if (! strncmp (rs6000_traceback_name, "no", 2))
-	rs6000_traceback = traceback_none;
-      else
-	error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>",
-	       rs6000_traceback_name);
-    }
-
-  if (rs6000_veclibabi_name)
-    {
-      if (strcmp (rs6000_veclibabi_name, "mass") == 0)
-	rs6000_veclib_handler = rs6000_builtin_vectorized_libmass;
-      else
-	error ("unknown vectorization library ABI type (%s) for "
-	       "-mveclibabi= switch", rs6000_veclibabi_name);
+      if (rs6000_veclibabi_name)
+	{
+	  if (strcmp (rs6000_veclibabi_name, "mass") == 0)
+	    rs6000_veclib_handler = rs6000_builtin_vectorized_libmass;
+	  else
+	    {
+	      error ("unknown vectorization library ABI type (%s) for "
+		     "-mveclibabi= switch", rs6000_veclibabi_name);
+	      ret = false;
+	    }
+	}
     }
 
   if (!rs6000_explicit_options.long_double)
@@ -2876,9 +2831,6 @@ rs6000_option_override_internal (const c
   if (flag_section_anchors)
     TARGET_NO_FP_IN_TOC = 1;
 
-  /* Handle -mtls-size option.  */
-  rs6000_parse_tls_size_option ();
-
 #ifdef SUBTARGET_OVERRIDE_OPTIONS
   SUBTARGET_OVERRIDE_OPTIONS;
 #endif
@@ -2980,76 +2932,79 @@ rs6000_option_override_internal (const c
 				    atoi (rs6000_sched_insert_nops_str));
     }
 
+  if (global_init_p)
+    {
 #ifdef TARGET_REGNAMES
-  /* If the user desires alternate register names, copy in the
-     alternate names now.  */
-  if (TARGET_REGNAMES)
-    memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
+      /* If the user desires alternate register names, copy in the
+	 alternate names now.  */
+      if (TARGET_REGNAMES)
+	memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
 #endif
 
-  /* Set aix_struct_return last, after the ABI is determined.
-     If -maix-struct-return or -msvr4-struct-return was explicitly
-     used, don't override with the ABI default.  */
-  if (!rs6000_explicit_options.aix_struct_ret)
-    aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
+      /* Set aix_struct_return last, after the ABI is determined.
+	 If -maix-struct-return or -msvr4-struct-return was explicitly
+	 used, don't override with the ABI default.  */
+      if (!rs6000_explicit_options.aix_struct_ret)
+	aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
 
 #if 0
-  /* IBM XL compiler defaults to unsigned bitfields.  */
-  if (TARGET_XL_COMPAT)
-    flag_signed_bitfields = 0;
-#endif
-
-  if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
-    REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
-
-  if (TARGET_TOC)
-    ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
-
-  /* We can only guarantee the availability of DI pseudo-ops when
-     assembling for 64-bit targets.  */
-  if (!TARGET_64BIT)
-    {
-      targetm.asm_out.aligned_op.di = NULL;
-      targetm.asm_out.unaligned_op.di = NULL;
-    }
-
-  /* Set branch target alignment, if not optimizing for size.  */
-  if (!optimize_size)
-    {
-      /* Cell wants to be aligned 8byte for dual issue.  Titan wants to be
-	 aligned 8byte to avoid misprediction by the branch predictor.  */
-      if (rs6000_cpu == PROCESSOR_TITAN
-	  || rs6000_cpu == PROCESSOR_CELL)
-	{
-	  if (align_functions <= 0)
-	    align_functions = 8;
-	  if (align_jumps <= 0)
-	    align_jumps = 8;
-	  if (align_loops <= 0)
-	    align_loops = 8;
- 	}
-      if (rs6000_align_branch_targets)
-	{
-	  if (align_functions <= 0)
-	    align_functions = 16;
-	  if (align_jumps <= 0)
-	    align_jumps = 16;
-	  if (align_loops <= 0)
-	    align_loops = 16;
-	}
-      if (align_jumps_max_skip <= 0)
-	align_jumps_max_skip = 15;
-      if (align_loops_max_skip <= 0)
-	align_loops_max_skip = 15;
-    }
-
-  /* Arrange to save and restore machine status around nested functions.  */
-  init_machine_status = rs6000_init_machine_status;
-
-  /* We should always be splitting complex arguments, but we can't break
-     Linux and Darwin ABIs at the moment.  For now, only AIX is fixed.  */
-  if (DEFAULT_ABI != ABI_AIX)
-    targetm.calls.split_complex_arg = NULL;
+      /* IBM XL compiler defaults to unsigned bitfields.  */
+      if (TARGET_XL_COMPAT)
+	flag_signed_bitfields = 0;
+#endif
+
+      if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+	REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
+
+      if (TARGET_TOC)
+	ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
+
+      /* We can only guarantee the availability of DI pseudo-ops when
+	 assembling for 64-bit targets.  */
+      if (!TARGET_64BIT)
+	{
+	  targetm.asm_out.aligned_op.di = NULL;
+	  targetm.asm_out.unaligned_op.di = NULL;
+	}
+
+      /* Set branch target alignment, if not optimizing for size.  */
+      if (!optimize_size)
+	{
+	  /* Cell wants to be aligned 8byte for dual issue.  Titan wants to be
+	     aligned 8byte to avoid misprediction by the branch predictor.  */
+	  if (rs6000_cpu == PROCESSOR_TITAN
+	      || rs6000_cpu == PROCESSOR_CELL)
+	    {
+	      if (align_functions <= 0)
+		align_functions = 8;
+	      if (align_jumps <= 0)
+		align_jumps = 8;
+	      if (align_loops <= 0)
+		align_loops = 8;
+	    }
+	  if (rs6000_align_branch_targets)
+	    {
+	      if (align_functions <= 0)
+		align_functions = 16;
+	      if (align_jumps <= 0)
+		align_jumps = 16;
+	      if (align_loops <= 0)
+		align_loops = 16;
+	    }
+	  if (align_jumps_max_skip <= 0)
+	    align_jumps_max_skip = 15;
+	  if (align_loops_max_skip <= 0)
+	    align_loops_max_skip = 15;
+	}
+
+      /* Arrange to save and restore machine status around nested functions.  */
+      init_machine_status = rs6000_init_machine_status;
+
+      /* We should always be splitting complex arguments, but we can't break
+	 Linux and Darwin ABIs at the moment.  For now, only AIX is fixed.  */
+      if (DEFAULT_ABI != ABI_AIX)
+	targetm.calls.split_complex_arg = NULL;
+    }
 
   /* Initialize rs6000_cost with the appropriate target costs.  */
   if (optimize_size)
@@ -3168,25 +3123,29 @@ rs6000_option_override_internal (const c
 	gcc_unreachable ();
       }
 
-  maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
-			 rs6000_cost->simultaneous_prefetches,
-			 global_options.x_param_values,
-			 global_options_set.x_param_values);
-  maybe_set_param_value (PARAM_L1_CACHE_SIZE, rs6000_cost->l1_cache_size,
-			 global_options.x_param_values,
-			 global_options_set.x_param_values);
-  maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
-			 rs6000_cost->cache_line_size,
-			 global_options.x_param_values,
-			 global_options_set.x_param_values);
-  maybe_set_param_value (PARAM_L2_CACHE_SIZE, rs6000_cost->l2_cache_size,
-			 global_options.x_param_values,
-			 global_options_set.x_param_values);
-
-  /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0)
-     can be optimized to ap = __builtin_next_arg (0).  */
-  if (DEFAULT_ABI != ABI_V4)
-    targetm.expand_builtin_va_start = NULL;
+  if (global_init_p)
+    {
+      maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
+			     rs6000_cost->simultaneous_prefetches,
+			     global_options.x_param_values,
+			     global_options_set.x_param_values);
+      maybe_set_param_value (PARAM_L1_CACHE_SIZE, rs6000_cost->l1_cache_size,
+			     global_options.x_param_values,
+			     global_options_set.x_param_values);
+      maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
+			     rs6000_cost->cache_line_size,
+			     global_options.x_param_values,
+			     global_options_set.x_param_values);
+      maybe_set_param_value (PARAM_L2_CACHE_SIZE, rs6000_cost->l2_cache_size,
+			     global_options.x_param_values,
+			     global_options_set.x_param_values);
+
+      /* If using typedef char *va_list, signal that
+	 __builtin_va_start (&ap, 0) can be optimized to
+	 ap = __builtin_next_arg (0).  */
+      if (DEFAULT_ABI != ABI_V4)
+	targetm.expand_builtin_va_start = NULL;
+    }
 
   /* Set up single/double float flags.  
      If TARGET_HARD_FLOAT is set, but neither single or double is set, 
@@ -3248,6 +3207,7 @@ rs6000_option_override_internal (const c
 		  error ("Unknown option for -mrecip=%s", q);
 		  invert = false;
 		  mask = 0;
+		  ret = false;
 		}
 	    }
 
@@ -3259,6 +3219,13 @@ rs6000_option_override_internal (const c
     }
 
   rs6000_init_hard_regno_mode_ok ();
+
+  /* Save the initial options in case the user does function specific options */
+  if (global_init_p)
+    target_option_default_node = target_option_current_node
+      = build_target_option_node ();
+
+  return ret;
 }
 
 /* Implement TARGET_OPTION_OVERRIDE.  On the RS/6000 this is used to
@@ -3267,9 +3234,10 @@ rs6000_option_override_internal (const c
 static void
 rs6000_option_override (void)
 {
-  rs6000_option_override_internal (OPTION_TARGET_CPU_DEFAULT);
+  (void) rs6000_option_override_internal (true);
 }
 
+
 /* Implement targetm.vectorize.builtin_mask_for_load.  */
 static tree
 rs6000_builtin_mask_for_load (void)
@@ -3674,23 +3642,6 @@ rs6000_parse_yes_no_option (const char *
     error ("unknown -m%s= option specified: '%s'", name, value);
 }
 
-/* Validate and record the size specified with the -mtls-size option.  */
-
-static void
-rs6000_parse_tls_size_option (void)
-{
-  if (rs6000_tls_size_string == 0)
-    return;
-  else if (strcmp (rs6000_tls_size_string, "16") == 0)
-    rs6000_tls_size = 16;
-  else if (strcmp (rs6000_tls_size_string, "32") == 0)
-    rs6000_tls_size = 32;
-  else if (strcmp (rs6000_tls_size_string, "64") == 0)
-    rs6000_tls_size = 64;
-  else
-    error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string);
-}
-
 /* Implement TARGET_OPTION_INIT_STRUCT.  */
 
 static void
@@ -4063,6 +4014,7 @@ rs6000_handle_option (size_t code, const
 {
   enum fpu_type_t fpu_type = FPU_NONE;
   int isel;
+  char *p, *q;
 
   switch (code)
     {
@@ -4102,11 +4054,11 @@ rs6000_handle_option (size_t code, const
 #if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
     case OPT_mcmodel_:
       if (strcmp (arg, "small") == 0)
-	cmodel = CMODEL_SMALL;
+	rs6000_current_cmodel = CMODEL_SMALL;
       else if (strcmp (arg, "medium") == 0)
-	cmodel = CMODEL_MEDIUM;
+	rs6000_current_cmodel = CMODEL_MEDIUM;
       else if (strcmp (arg, "large") == 0)
-	cmodel = CMODEL_LARGE;
+	rs6000_current_cmodel = CMODEL_LARGE;
       else
 	{
 	  error ("invalid option for -mcmodel: '%s'", arg);
@@ -4207,7 +4159,45 @@ rs6000_handle_option (size_t code, const
       break;
 
     case OPT_mdebug_:
-      rs6000_debug_name = arg;
+      p = ASTRDUP (arg);
+      rs6000_debug = 0;
+
+      while ((q = strtok (p, ",")) != NULL)
+	{
+	  unsigned mask = 0;
+	  bool invert;
+
+	  p = NULL;
+	  if (*q == '!')
+	    {
+	      invert = true;
+	      q++;
+	    }
+	  else
+	    invert = false;
+
+	  if (! strcmp (q, "all"))
+	    mask = MASK_DEBUG_ALL;
+	  else if (! strcmp (q, "stack"))
+	    mask = MASK_DEBUG_STACK;
+	  else if (! strcmp (q, "arg"))
+	    mask = MASK_DEBUG_ARG;
+	  else if (! strcmp (q, "reg"))
+	    mask = MASK_DEBUG_REG;
+	  else if (! strcmp (q, "addr"))
+	    mask = MASK_DEBUG_ADDR;
+	  else if (! strcmp (q, "cost"))
+	    mask = MASK_DEBUG_COST;
+	  else if (! strcmp (q, "target"))
+	    mask = MASK_DEBUG_TARGET;
+	  else
+	    error ("unknown -mdebug-%s switch", q);
+
+	  if (invert)
+	    rs6000_debug &= ~mask;
+	  else	
+	    rs6000_debug |= mask;
+	}
       break;
 
 #ifdef TARGET_USES_SYSV4_OPT
@@ -4220,7 +4210,14 @@ rs6000_handle_option (size_t code, const
       break;
 
     case OPT_mtls_size_:
-      rs6000_tls_size_string = arg;
+      if (strcmp (arg, "16") == 0)
+	rs6000_tls_size = 16;
+      else if (strcmp (arg, "32") == 0)
+	rs6000_tls_size = 32;
+      else if (strcmp (arg, "64") == 0)
+	rs6000_tls_size = 64;
+      else
+	error ("bad value %qs for -mtls-size switch", arg);
       break;
 
     case OPT_mrelocatable:
@@ -4310,14 +4307,28 @@ rs6000_handle_option (size_t code, const
 
     case OPT_mcpu_:
       rs6000_select[1].string = arg;
+      rs6000_cpu_index = rs6000_cpu_name_lookup (arg);
+      if (rs6000_cpu_index < 0)
+	error ("bad value (%s) for -mcpu", arg);
       break;
 
     case OPT_mtune_:
       rs6000_select[2].string = arg;
+      rs6000_tune_index = rs6000_cpu_name_lookup (arg);
+      if (rs6000_tune_index < 0)
+	error ("bad value (%s) for -mtune", arg);
       break;
 
     case OPT_mtraceback_:
-      rs6000_traceback_name = arg;
+      if (! strncmp (arg, "full", 4))
+	rs6000_traceback = traceback_full;
+      else if (! strncmp (arg, "part", 4))
+	rs6000_traceback = traceback_part;
+      else if (! strncmp (arg, "no", 2))
+	rs6000_traceback = traceback_none;
+      else
+	error ("unknown -mtraceback arg %qs; expecting %<full%>, "
+	       "%<partial%> or %<none%>", arg);
       break;
 
     case OPT_mfloat_gprs_:
@@ -6807,6 +6818,9 @@ rs6000_conditional_register_usage (void)
 {
   int i;
 
+  if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
+    fprintf (stderr, "rs6000_conditional_register_usage called\n");
+
   /* Set MQ register fixed (already call_used) if not POWER
      architecture (RIOS1, RIOS2, RSC, and PPC601) so that it will not
      be allocated.  */
@@ -27123,6 +27137,581 @@ rs6000_final_prescan_insn (rtx insn, rtx
 }
 
 
+/* Mask options that we want to support inside of attribute((target)) and
+   #pragma GCC target operations.  Note, we do not include things like
+   64/32-bit, endianess, hard/soft floating point, etc. that would have
+   different calling sequences.  */
+
+struct rs6000_opt_mask {
+  const char *name;		/* option name */
+  int mask;			/* mask to set */
+  bool invert;			/* invert sense of mask */
+  bool valid_target;		/* option is a target option */
+};
+
+static struct rs6000_opt_mask const rs6000_opt_masks[] =
+{
+  { "altivec",		MASK_ALTIVEC,		false, true  },
+  { "cmpb",		MASK_CMPB,		false, true  },
+  { "dlmzb",		MASK_DLMZB,		false, true  },
+  { "fprnd",		MASK_FPRND,		false, true  },
+  { "hard-dfp",		MASK_DFP,		false, true  },
+  { "isel",		MASK_ISEL,		false, true  },
+  { "mfcrf",		MASK_MFCRF,		false, true  },
+  { "mfpgpr",		MASK_MFPGPR,		false, true  },
+  { "mulhw",		MASK_MULHW,		false, true  },
+  { "multiple",		MASK_MULTIPLE,		false, true  },
+  { "update",		MASK_NO_UPDATE,		true , true  },
+  { "popcntb",		MASK_POPCNTB,		false, true  },
+  { "popcntd",		MASK_POPCNTD,		false, true  },
+  { "powerpc-gfxopt",	MASK_PPC_GFXOPT,	false, true  },
+  { "powerpc-gpopt",	MASK_PPC_GPOPT,		false, true  },
+  { "recip-precision",	MASK_RECIP_PRECISION,	false, true  },
+  { "string",		MASK_STRING,		false, true  },
+  { "vsx",		MASK_VSX,		false, true  },
+#ifdef MASK_64BIT
+  { "64",		MASK_64BIT,		false, false },
+  { "32",		MASK_64BIT,		true,  false },
+#endif
+#ifdef MASK_EABI
+  { "eabi",		MASK_EABI,		false, false },
+#endif
+#ifdef MASK_LITTLE_ENDIAN
+  { "little",		MASK_LITTLE_ENDIAN,	false, false },
+  { "big",		MASK_LITTLE_ENDIAN,	true,  false },
+#endif
+#ifdef MASK_RELOCATABLE
+  { "relocatable",	MASK_RELOCATABLE,	false, false },
+#endif
+#ifdef MASK_STRICT_ALIGN
+  { "strict-align",	MASK_STRICT_ALIGN,	false, false },
+#endif
+  { "power",		MASK_POWER,		false, false },
+  { "power2",		MASK_POWER2,		false, false },
+  { "powerpc",		MASK_POWERPC,		false, false },
+  { "soft-float",	MASK_SOFT_FLOAT,	false, false },
+  { "string",		MASK_STRING,		false, false },
+};
+
+/* Option variables that we want to support inside attribute((target)) and
+   #pragma GCC target operations.  */
+
+struct rs6000_opt_var {
+  const char *name;		/* option name */
+  size_t global_offset;		/* offset of the option in global_options.  */
+  size_t target_offset;		/* offset of the option in target optiosn.  */
+};
+
+static struct rs6000_opt_var const rs6000_opt_vars[] =
+{
+  { "friz",
+    offsetof (struct gcc_options, x_TARGET_FRIZ),
+    offsetof (struct cl_target_option, x_TARGET_FRIZ), },
+  { "avoid-indexed-addresses",
+    offsetof (struct gcc_options, x_TARGET_AVOID_XFORM),
+    offsetof (struct cl_target_option, x_TARGET_AVOID_XFORM) },
+  { "fused-madd",
+    offsetof (struct gcc_options, x_TARGET_FUSED_MADD),
+    offsetof (struct cl_target_option, x_TARGET_FUSED_MADD), },
+  { "paired",
+    offsetof (struct gcc_options, x_rs6000_paired_float),
+    offsetof (struct cl_target_option, x_rs6000_paired_float), },
+  { "longcall",
+    offsetof (struct gcc_options, x_rs6000_default_long_calls),
+    offsetof (struct cl_target_option, x_rs6000_default_long_calls), },
+};
+
+/* Inner function to handle attribute((target("..."))) and #pragma GCC target
+   parsing.  Return true if there were no errors.  */
+
+static bool
+rs6000_inner_target_options (tree args, bool attr_p)
+{
+  bool ret = true;
+
+  if (args == NULL_TREE)
+    ;
+
+  else if (TREE_CODE (args) == STRING_CST)
+    {
+      char *p = ASTRDUP (TREE_STRING_POINTER (args));
+      char *q;
+
+      while ((q = strtok (p, ",")) != NULL)
+	{
+	  bool error_p = false;
+	  bool not_valid_p = false;
+	  const char *cpu_opt = NULL;
+
+	  p = NULL;
+	  if (strncmp (q, "cpu=", 4) == 0)
+	    {
+	      int cpu_index = rs6000_cpu_name_lookup (q+4);
+	      if (cpu_index >= 0)
+		rs6000_cpu_index = cpu_index;
+	      else
+		{
+		  error_p = true;
+		  cpu_opt = q+4;
+		}
+	    }
+	  else if (strncmp (q, "tune=", 5) == 0)
+	    {
+	      int tune_index = rs6000_cpu_name_lookup (q+5);
+	      if (tune_index >= 0)
+		rs6000_tune_index = tune_index;
+	      else
+		{
+		  error_p = true;
+		  cpu_opt = q+5;
+		}
+	    }
+	  else
+	    {
+	      size_t i;
+	      bool invert = false;
+	      char *r = q;
+
+	      error_p = true;
+	      if (strncmp (r, "no-", 3) == 0)
+		{
+		  invert = true;
+		  r += 3;
+		}
+
+	      for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
+		if (strcmp (r, rs6000_opt_masks[i].name) == 0)
+		  {
+		    int mask = rs6000_opt_masks[i].mask;
+
+		    if (!rs6000_opt_masks[i].valid_target)
+		      not_valid_p = true;
+		    else
+		      {
+			error_p = false;
+			target_flags_explicit |= mask;
+
+			if (rs6000_opt_masks[i].invert)
+			  invert = !invert;
+
+			if (invert)
+			  target_flags &= ~mask;
+			else
+			  target_flags |= mask;
+		      }
+		    break;
+		  }
+
+	      if (error_p && !not_valid_p)
+		{
+		  for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
+		    if (strcmp (r, rs6000_opt_vars[i].name) == 0)
+		      {
+			size_t j = rs6000_opt_vars[i].global_offset;
+			((int *) &global_options)[j] = !invert;
+			error_p = false;
+			break;
+		      }
+		}
+	    }
+
+	  if (error_p)
+	    {
+	      const char *eprefix, *esuffix;
+
+	      ret = false;
+	      if (attr_p)
+		{
+		  eprefix = "__attribute__((__target__(";
+		  esuffix = ")))";
+		}
+	      else
+		{
+		  eprefix = "#pragma GCC target ";
+		  esuffix = "";
+		}
+
+	      if (cpu_opt)
+		error ("Invalid cpu \"%s\" for %s\"%s\"%s", cpu_opt, eprefix,
+		       q, esuffix);
+	      else if (not_valid_p)
+		error ("%s\"%s\"%s is not allowed", eprefix, q, esuffix);
+	      else
+		error ("%s\"%s\"%s is invalid", eprefix, q, esuffix);
+	    }
+	}
+    }
+
+  else if (TREE_CODE (args) == TREE_LIST)
+    {
+      do
+	{
+	  tree value = TREE_VALUE (args);
+	  if (value)
+	    {
+	      bool ret2 = rs6000_inner_target_options (value, attr_p);
+	      if (!ret2)
+		ret = false;
+	    }
+	  args = TREE_CHAIN (args);
+	}
+      while (args != NULL_TREE);
+    }
+
+  else
+    gcc_unreachable ();
+
+  return ret;
+}
+
+/* Print out the target options as a list for -mdebug=target.  */
+
+static void
+rs6000_debug_target_options (tree args, const char *prefix)
+{
+  if (args == NULL_TREE)
+    fprintf (stderr, "%s<NULL>", prefix);
+
+  else if (TREE_CODE (args) == STRING_CST)
+    {
+      char *p = ASTRDUP (TREE_STRING_POINTER (args));
+      char *q;
+
+      while ((q = strtok (p, ",")) != NULL)
+	{
+	  p = NULL;
+	  fprintf (stderr, "%s\"%s\"", prefix, q);
+	  prefix = ", ";
+	}
+    }
+
+  else if (TREE_CODE (args) == TREE_LIST)
+    {
+      do
+	{
+	  tree value = TREE_VALUE (args);
+	  if (value)
+	    {
+	      rs6000_debug_target_options (value, prefix);
+	      prefix = ", ";
+	    }
+	  args = TREE_CHAIN (args);
+	}
+      while (args != NULL_TREE);
+    }
+
+  else
+    gcc_unreachable ();
+
+  return;
+}
+
+
+/* Hook to validate attribute((target("..."))).  */
+
+static bool
+rs6000_valid_attribute_p (tree fndecl,
+			  tree ARG_UNUSED (name),
+			  tree args,
+			  int flags)
+{
+  struct cl_target_option cur_target;
+  bool ret;
+  tree old_optimize = build_optimization_node ();
+  tree new_target, new_optimize;
+  tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+  gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE));
+
+  if (TARGET_DEBUG_TARGET)
+    {
+      tree tname = DECL_NAME (fndecl);
+      fprintf (stderr, "\n==================== rs6000_valid_attribute_p:\n");
+      if (tname)
+	fprintf (stderr, "function: %.*s\n",
+		 (int) IDENTIFIER_LENGTH (tname),
+		 IDENTIFIER_POINTER (tname));
+      else
+	fprintf (stderr, "function: unknown\n");
+  
+      fprintf (stderr, "args:");
+      rs6000_debug_target_options (args, " ");
+      fprintf (stderr, "\n");
+
+      if (flags)
+	fprintf (stderr, "flags: 0x%x\n", flags);
+
+      fprintf (stderr, "--------------------\n");
+    }
+
+  old_optimize = build_optimization_node ();
+  func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+  /* If the function changed the optimization levels as well as setting target
+     options, start with the optimizations specified.  */
+  if (func_optimize && func_optimize != old_optimize)
+    cl_optimization_restore (&global_options,
+			     TREE_OPTIMIZATION (func_optimize));
+
+  /* The target attributes may also change some optimization flags, so update
+     the optimization options if necessary.  */
+  cl_target_option_save (&cur_target, &global_options);
+  ret = rs6000_inner_target_options (args, true);
+
+  /* Set up any additional state.  */
+  if (ret)
+    {
+      ret = rs6000_option_override_internal (false);
+      new_target = build_target_option_node ();
+    }
+  else
+    new_target = NULL;
+
+  new_optimize = build_optimization_node ();
+
+  if (!new_target)
+    ret = false;
+
+  else if (fndecl)
+    {
+      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
+
+      if (old_optimize != new_optimize)
+	DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+    }
+
+  cl_target_option_restore (&global_options, &cur_target);
+
+  if (old_optimize != new_optimize)
+    cl_optimization_restore (&global_options,
+			     TREE_OPTIMIZATION (old_optimize));
+
+  return ret;
+}
+
+
+/* Hook to validate the current #pragma GCC target and set the state, and
+   update the macros based on what was changed.  If ARGS is NULL, then
+   POP_TARGET is used to reset the options.  */
+
+bool
+rs6000_pragma_target_parse (tree args, tree pop_target)
+{
+  tree cur_tree;
+  bool ret;
+
+  if (TARGET_DEBUG_TARGET)
+    {
+      fprintf (stderr, "\n==================== rs6000_pragma_target_parse\n");
+      fprintf (stderr, "args:");
+      rs6000_debug_target_options (args, " ");
+      fprintf (stderr, "\n");
+
+      if (pop_target)
+	{
+	  fprintf (stderr, "pop_target:\n");
+	  debug_tree (pop_target);
+	}
+      else
+	fprintf (stderr, "pop_target: <NULL>\n");
+
+      fprintf (stderr, "--------------------\n");
+    }
+
+  if (! args)
+    {
+      ret = true;
+      cur_tree = ((pop_target)
+		  ? pop_target
+		  : target_option_default_node);
+      cl_target_option_restore (&global_options,
+				TREE_TARGET_OPTION (cur_tree));
+    }
+  else
+    {
+      ret = rs6000_inner_target_options (args, false);
+      cur_tree = build_target_option_node ();
+
+      if (!cur_tree)
+	ret = false;
+    }
+
+  if (cur_tree)
+    target_option_current_node = cur_tree;
+
+  return ret;
+}
+
+
+/* Remember the last target of rs6000_set_current_function.  */
+static GTY(()) tree rs6000_previous_fndecl;
+
+/* Establish appropriate back-end context for processing the function
+   FNDECL.  The argument might be NULL to indicate processing at top
+   level, outside of any function scope.  */
+static void
+rs6000_set_current_function (tree fndecl)
+{
+  tree old_tree = (rs6000_previous_fndecl
+		   ? DECL_FUNCTION_SPECIFIC_TARGET (rs6000_previous_fndecl)
+		   : NULL_TREE);
+
+  tree new_tree = (fndecl
+		   ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
+		   : NULL_TREE);
+
+  if (TARGET_DEBUG_TARGET)
+    {
+      bool print_final = false;
+      fprintf (stderr, "\n==================== rs6000_set_current_function");
+
+      if (fndecl)
+	fprintf (stderr, ", fndecl %s (%p)",
+		 (DECL_NAME (fndecl)
+		  ? IDENTIFIER_POINTER (DECL_NAME (fndecl))
+		  : "<unknown>"), (void *)fndecl);
+
+      if (rs6000_previous_fndecl)
+	fprintf (stderr, ", prev_fndecl (%p)", (void *)rs6000_previous_fndecl);
+
+      fprintf (stderr, "\n");
+      if (new_tree)
+	{
+	  fprintf (stderr, "\nnew fndecl target specific options:\n");
+	  debug_tree (new_tree);
+	  print_final = true;
+	}
+
+      if (old_tree)
+	{
+	  fprintf (stderr, "\nold fndecl target specific options:\n");
+	  debug_tree (old_tree);
+	  print_final = true;
+	}
+
+      if (print_final)
+	fprintf (stderr, "--------------------\n");
+    }
+
+  /* Only change the context if the function changes.  This hook is called
+     several times in the course of compiling a function, and we don't want to
+     slow things down too much or call target_reinit when it isn't safe.  */
+  if (fndecl && fndecl != rs6000_previous_fndecl)
+    {
+      rs6000_previous_fndecl = fndecl;
+      if (old_tree == new_tree)
+	;
+
+      else if (new_tree)
+	{
+	  cl_target_option_restore (&global_options,
+				    TREE_TARGET_OPTION (new_tree));
+	  target_reinit ();
+	}
+
+      else if (old_tree)
+	{
+	  struct cl_target_option *def
+	    = TREE_TARGET_OPTION (target_option_current_node);
+
+	  cl_target_option_restore (&global_options, def);
+	  target_reinit ();
+	}
+    }
+}
+
+
+/* Save the current options */
+
+static void
+rs6000_function_specific_save (struct cl_target_option *ptr)
+{
+  ptr->rs6000_target_flags_explicit = target_flags_explicit;
+}
+
+/* Restore the current options */
+
+static void
+rs6000_function_specific_restore (struct cl_target_option *ptr)
+{
+  target_flags_explicit = ptr->rs6000_target_flags_explicit;
+  (void) rs6000_option_override_internal (false);
+}
+
+/* Print the current options */
+
+static void
+rs6000_function_specific_print (FILE *file, int indent,
+				struct cl_target_option *ptr)
+{
+  size_t i;
+  int flags = ptr->x_target_flags;
+
+  /* Print the various mask options.  */
+  for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
+    if ((flags & rs6000_opt_masks[i].mask) != 0)
+      {
+	flags &= ~ rs6000_opt_masks[i].mask;
+	fprintf (file, "%*s-m%s%s\n", indent, "",
+		 rs6000_opt_masks[i].invert ? "no-" : "",
+		 rs6000_opt_masks[i].name);
+      }
+
+  /* Print the various options that are variables.  */
+  for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
+    {
+      size_t j = rs6000_opt_vars[i].target_offset;
+      if (((signed char *) ptr)[j])
+	fprintf (file, "%*s-m%s\n", indent, "",
+		 rs6000_opt_vars[i].name);
+    }
+}
+
+
+/* Hook to determine if one function can safely inline another.  */
+
+static bool
+rs6000_can_inline_p (tree caller, tree callee)
+{
+  bool ret = false;
+  tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
+  tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
+
+  /* If callee has no option attributes, then it is ok to inline.  */
+  if (!callee_tree)
+    ret = true;
+
+  /* If caller has no option attributes, but callee does then it is not ok to
+     inline.  */
+  else if (!caller_tree)
+    ret = false;
+
+  else
+    {
+      struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
+      struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
+
+      /* Callee's options should a subset of the caller's, i.e. a vsx function
+	 can inline an altivec function but a non-vsx function can't inline a
+	 vsx function.  */
+      if ((caller_opts->x_target_flags & callee_opts->x_target_flags)
+	  == callee_opts->x_target_flags)
+	ret = true;
+    }
+
+  if (TARGET_DEBUG_TARGET)
+    fprintf (stderr, "rs6000_can_inline_p:, caller %s, callee %s, %s inline\n",
+	     (DECL_NAME (caller)
+	      ? IDENTIFIER_POINTER (DECL_NAME (caller))
+	      : "<unknown>"),
+	     (DECL_NAME (callee)
+	      ? IDENTIFIER_POINTER (DECL_NAME (callee))
+	      : "<unknown>"),
+	     (ret ? "can" : "cannot"));
+
+  return ret;
+}
+
 /* Allocate a stack temp and fixup the address so it meets the particular
    memory requirements (either offetable or REG+REG addressing).  */
 
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -29,6 +29,10 @@
 /* Note that some other tm.h files include this one and then override
    many of the definitions.  */
 
+#ifndef RS6000_OPTS_H
+#include "config/rs6000/rs6000-opts.h"
+#endif
+
 /* Definitions for the object file format.  These are set at
    compile-time.  */
 
@@ -299,16 +303,6 @@ extern const char *host_detect_local_cpu
 #define TARGET_SECURE_PLT 0
 #endif
 
-/* Code model for 64-bit linux.
-   small: 16-bit toc offsets.
-   medium: 32-bit toc offsets, static data and code within 2G of TOC pointer.
-   large: 32-bit toc offsets, no limit on static data and code.  */
-enum rs6000_cmodel {
-  CMODEL_SMALL,
-  CMODEL_MEDIUM,
-  CMODEL_LARGE
-};
-
 #ifndef TARGET_CMODEL
 #define TARGET_CMODEL CMODEL_SMALL
 #endif
@@ -338,40 +332,6 @@ enum rs6000_cmodel {
 
 #define TARGET_DEFAULT (MASK_POWER | MASK_MULTIPLE | MASK_STRING)
 
-/* Processor type.  Order must match cpu attribute in MD file.  */
-enum processor_type
- {
-   PROCESSOR_RIOS1,
-   PROCESSOR_RIOS2,
-   PROCESSOR_RS64A,
-   PROCESSOR_MPCCORE,
-   PROCESSOR_PPC403,
-   PROCESSOR_PPC405,
-   PROCESSOR_PPC440,
-   PROCESSOR_PPC476,
-   PROCESSOR_PPC601,
-   PROCESSOR_PPC603,
-   PROCESSOR_PPC604,
-   PROCESSOR_PPC604e,
-   PROCESSOR_PPC620,
-   PROCESSOR_PPC630,
-   PROCESSOR_PPC750,
-   PROCESSOR_PPC7400,
-   PROCESSOR_PPC7450,
-   PROCESSOR_PPC8540,
-   PROCESSOR_PPCE300C2,
-   PROCESSOR_PPCE300C3,
-   PROCESSOR_PPCE500MC,
-   PROCESSOR_PPCE500MC64,
-   PROCESSOR_POWER4,
-   PROCESSOR_POWER5,
-   PROCESSOR_POWER6,
-   PROCESSOR_POWER7,
-   PROCESSOR_CELL,
-   PROCESSOR_PPCA2,
-   PROCESSOR_TITAN
-};
-
 /* FPU operations supported. 
    Each use of TARGET_SINGLE_FLOAT or TARGET_DOUBLE_FLOAT must 
    also test TARGET_HARD_FLOAT.  */
@@ -381,8 +341,6 @@ enum processor_type
 #define TARGET_SIMPLE_FPU   0
 #define TARGET_XILINX_FPU   0
 
-extern enum processor_type rs6000_cpu;
-
 /* Recast the processor type to the cpu attribute.  */
 #define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu)
 
@@ -396,47 +354,12 @@ extern enum processor_type rs6000_cpu;
 #define PROCESSOR_DEFAULT   PROCESSOR_RIOS1
 #define PROCESSOR_DEFAULT64 PROCESSOR_RS64A
 
-/* FP processor type.  */
-enum fpu_type_t
-{
-	FPU_NONE,		/* No FPU */
-	FPU_SF_LITE,		/* Limited Single Precision FPU */
-	FPU_DF_LITE,		/* Limited Double Precision FPU */
-	FPU_SF_FULL,		/* Full Single Precision FPU */
-	FPU_DF_FULL		/* Full Double Single Precision FPU */
-};
-
 extern enum fpu_type_t fpu_type;
 
 /* Specify the dialect of assembler to use.  New mnemonics is dialect one
    and the old mnemonics are dialect zero.  */
 #define ASSEMBLER_DIALECT (TARGET_NEW_MNEMONICS ? 1 : 0)
 
-/* Types of costly dependences.  */
-enum rs6000_dependence_cost
- {
-   max_dep_latency = 1000,
-   no_dep_costly,
-   all_deps_costly,
-   true_store_to_load_dep_costly,
-   store_to_load_dep_costly
- };
-
-/* Types of nop insertion schemes in sched target hook sched_finish.  */
-enum rs6000_nop_insertion
-  {
-    sched_finish_regroup_exact = 1000,
-    sched_finish_pad_groups,
-    sched_finish_none
-  };
-
-/* Dispatch group termination caused by an insn.  */
-enum group_termination
-  {
-    current_group,
-    previous_group
-  };
-
 /* rs6000_select[0] is reserved for the default cpu defined via --with-cpu */
 struct rs6000_cpu_select
 {
@@ -449,42 +372,25 @@ struct rs6000_cpu_select
 extern struct rs6000_cpu_select rs6000_select[];
 
 /* Debug support */
-extern const char *rs6000_debug_name;	/* Name for -mdebug-xxxx option */
-extern int rs6000_debug_stack;		/* debug stack applications */
-extern int rs6000_debug_arg;		/* debug argument handling */
-extern int rs6000_debug_reg;		/* debug register handling */
-extern int rs6000_debug_addr;		/* debug memory addressing */
-extern int rs6000_debug_cost;		/* debug rtx_costs */
-
-#define	TARGET_DEBUG_STACK	rs6000_debug_stack
-#define	TARGET_DEBUG_ARG	rs6000_debug_arg
-#define TARGET_DEBUG_REG	rs6000_debug_reg
-#define TARGET_DEBUG_ADDR	rs6000_debug_addr
-#define TARGET_DEBUG_COST	rs6000_debug_cost
-
-extern const char *rs6000_traceback_name; /* Type of traceback table.  */
-
-/* These are separate from target_flags because we've run out of bits
-   there.  */
-extern int rs6000_long_double_type_size;
-extern int rs6000_ieeequad;
-extern int rs6000_altivec_abi;
-extern int rs6000_spe_abi;
-extern int rs6000_spe;
-extern int rs6000_float_gprs;
-extern int rs6000_alignment_flags;
-extern const char *rs6000_sched_insert_nops_str;
-extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
-
-/* Describe which vector unit to use for a given machine mode.  */
-enum rs6000_vector {
-  VECTOR_NONE,			/* Type is not  a vector or not supported */
-  VECTOR_ALTIVEC,		/* Use altivec for vector processing */
-  VECTOR_VSX,			/* Use VSX for vector processing */
-  VECTOR_PAIRED,		/* Use paired floating point for vectors */
-  VECTOR_SPE,			/* Use SPE for vector processing */
-  VECTOR_OTHER			/* Some other vector unit */
-};
+#define MASK_DEBUG_STACK	0x01	/* debug stack applications */
+#define	MASK_DEBUG_ARG		0x02	/* debug argument handling */
+#define MASK_DEBUG_REG		0x04	/* debug register handling */
+#define MASK_DEBUG_ADDR		0x08	/* debug memory addressing */
+#define MASK_DEBUG_COST		0x10	/* debug rtx codes */
+#define MASK_DEBUG_TARGET	0x20	/* debug target attribute/pragma */
+#define MASK_DEBUG_ALL		(MASK_DEBUG_STACK \
+				 | MASK_DEBUG_ARG \
+				 | MASK_DEBUG_REG \
+				 | MASK_DEBUG_ADDR \
+				 | MASK_DEBUG_COST \
+				 | MASK_DEBUG_TARGET)
+
+#define	TARGET_DEBUG_STACK	(rs6000_debug & MASK_DEBUG_STACK)
+#define	TARGET_DEBUG_ARG	(rs6000_debug & MASK_DEBUG_ARG)
+#define TARGET_DEBUG_REG	(rs6000_debug & MASK_DEBUG_REG)
+#define TARGET_DEBUG_ADDR	(rs6000_debug & MASK_DEBUG_ADDR)
+#define TARGET_DEBUG_COST	(rs6000_debug & MASK_DEBUG_COST)
+#define TARGET_DEBUG_TARGET	(rs6000_debug & MASK_DEBUG_TARGET)
 
 extern enum rs6000_vector rs6000_vector_unit[];
 
@@ -628,6 +534,7 @@ extern unsigned char rs6000_recip_bits[]
 /* Target pragma.  */
 #define REGISTER_TARGET_PRAGMAS() do {				\
   c_register_pragma (0, "longcall", rs6000_pragma_longcall);	\
+  targetm.target_option.pragma_parse = rs6000_pragma_target_parse; \
   targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \
 } while (0)
 
@@ -1465,16 +1372,6 @@ extern enum reg_class rs6000_constraints
 
 /* Stack layout; function entry, exit and calling.  */
 
-/* Enumeration to give which calling sequence to use.  */
-enum rs6000_abi {
-  ABI_NONE,
-  ABI_AIX,			/* IBM's AIX */
-  ABI_V4,			/* System V.4/eabi */
-  ABI_DARWIN			/* Apple's Darwin (OS X kernel) */
-};
-
-extern enum rs6000_abi rs6000_current_abi;	/* available for use by subtarget */
-
 /* Define this if pushing a word on the stack
    makes the stack pointer a smaller address.  */
 #define STACK_GROWS_DOWNWARD
Index: gcc/config/rs6000/aix64.opt
===================================================================
--- gcc/config/rs6000/aix64.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/aix64.opt	(working copy)
@@ -28,5 +28,5 @@ Target Report RejectNegative Negative(ma
 Compile for 32-bit pointers
 
 mpe
-Target Report RejectNegative Var(internal_nothing_1)
+Target Report RejectNegative Var(internal_nothing_1) Save
 Support message passing with the Parallel Environment
Index: gcc/config/rs6000/sysv4.h
===================================================================
--- gcc/config/rs6000/sysv4.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/sysv4.h	(working copy)
@@ -41,16 +41,6 @@
 #undef	ASM_DEFAULT_SPEC
 #define	ASM_DEFAULT_SPEC "-mppc"
 
-/* Small data support types.  */
-enum rs6000_sdata_type {
-  SDATA_NONE,			/* No small data support.  */
-  SDATA_DATA,			/* Just put data in .sbss/.sdata, don't use relocs.  */
-  SDATA_SYSV,			/* Use r13 to point to .sdata/.sbss.  */
-  SDATA_EABI			/* Use r13 like above, r2 points to .sdata2/.sbss2.  */
-};
-
-extern enum rs6000_sdata_type rs6000_sdata;
-
 #define	TARGET_TOC		((target_flags & MASK_64BIT)		\
 				 || ((target_flags & (MASK_RELOCATABLE	\
 						      | MASK_MINIMAL_TOC)) \
@@ -70,10 +60,6 @@ extern enum rs6000_sdata_type rs6000_sda
 #define TARGET_SECURE_PLT	secure_plt
 #endif
 
-extern const char *rs6000_abi_name;
-extern const char *rs6000_sdata_name;
-extern const char *rs6000_tls_size_string; /* For -mtls-size= */
-
 #define SDATA_DEFAULT_SIZE 8
 
 /* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 0)
+++ gcc/config/rs6000/rs6000-opts.h	(revision 166071)
@@ -0,0 +1,144 @@
+/* Definitions of target machine needed for option handling for GNU compiler,
+   for IBM RS/6000.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef RS6000_OPTS_H
+#define RS6000_OPTS_H
+
+/* Processor type.  Order must match cpu attribute in MD file.  */
+enum processor_type
+ {
+   PROCESSOR_RIOS1,
+   PROCESSOR_RIOS2,
+   PROCESSOR_RS64A,
+   PROCESSOR_MPCCORE,
+   PROCESSOR_PPC403,
+   PROCESSOR_PPC405,
+   PROCESSOR_PPC440,
+   PROCESSOR_PPC476,
+   PROCESSOR_PPC601,
+   PROCESSOR_PPC603,
+   PROCESSOR_PPC604,
+   PROCESSOR_PPC604e,
+   PROCESSOR_PPC620,
+   PROCESSOR_PPC630,
+   PROCESSOR_PPC750,
+   PROCESSOR_PPC7400,
+   PROCESSOR_PPC7450,
+   PROCESSOR_PPC8540,
+   PROCESSOR_PPCE300C2,
+   PROCESSOR_PPCE300C3,
+   PROCESSOR_PPCE500MC,
+   PROCESSOR_PPCE500MC64,
+   PROCESSOR_POWER4,
+   PROCESSOR_POWER5,
+   PROCESSOR_POWER6,
+   PROCESSOR_POWER7,
+   PROCESSOR_CELL,
+   PROCESSOR_PPCA2,
+   PROCESSOR_TITAN
+};
+
+/* FP processor type.  */
+enum fpu_type_t
+{
+  FPU_NONE,			/* No FPU */
+  FPU_SF_LITE,			/* Limited Single Precision FPU */
+  FPU_DF_LITE,			/* Limited Double Precision FPU */
+  FPU_SF_FULL,			/* Full Single Precision FPU */
+  FPU_DF_FULL			/* Full Double Single Precision FPU */
+};
+
+/* Types of costly dependences.  */
+enum rs6000_dependence_cost
+{
+  max_dep_latency = 1000,
+  no_dep_costly,
+  all_deps_costly,
+  true_store_to_load_dep_costly,
+  store_to_load_dep_costly
+};
+
+/* Types of nop insertion schemes in sched target hook sched_finish.  */
+enum rs6000_nop_insertion
+{
+  sched_finish_regroup_exact = 1000,
+  sched_finish_pad_groups,
+  sched_finish_none
+};
+
+/* Dispatch group termination caused by an insn.  */
+enum group_termination
+{
+  current_group,
+  previous_group
+};
+
+/* Enumeration to give which calling sequence to use.  */
+enum rs6000_abi {
+  ABI_NONE,
+  ABI_AIX,			/* IBM's AIX */
+  ABI_V4,			/* System V.4/eabi */
+  ABI_DARWIN			/* Apple's Darwin (OS X kernel) */
+};
+
+/* Small data support types.  */
+enum rs6000_sdata_type {
+  SDATA_NONE,			/* No small data support.  */
+  SDATA_DATA,			/* Just put data in .sbss/.sdata, don't use relocs.  */
+  SDATA_SYSV,			/* Use r13 to point to .sdata/.sbss.  */
+  SDATA_EABI			/* Use r13 like above, r2 points to .sdata2/.sbss2.  */
+};
+
+/* Type of traceback to use.  */
+enum  rs6000_traceback_type {
+  traceback_default = 0,
+  traceback_none,
+  traceback_part,
+  traceback_full
+};
+
+/* Code model for 64-bit linux.
+   small: 16-bit toc offsets.
+   medium: 32-bit toc offsets, static data and code within 2G of TOC pointer.
+   large: 32-bit toc offsets, no limit on static data and code.  */
+enum rs6000_cmodel {
+  CMODEL_SMALL,
+  CMODEL_MEDIUM,
+  CMODEL_LARGE
+};
+
+/* Describe which vector unit to use for a given machine mode.  */
+enum rs6000_vector {
+  VECTOR_NONE,			/* Type is not  a vector or not supported */
+  VECTOR_ALTIVEC,		/* Use altivec for vector processing */
+  VECTOR_VSX,			/* Use VSX for vector processing */
+  VECTOR_PAIRED,		/* Use paired floating point for vectors */
+  VECTOR_SPE,			/* Use SPE for vector processing */
+  VECTOR_OTHER			/* Some other vector unit */
+};
+
+#endif
Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/config/rs6000/linux64.h	(working copy)
@@ -65,10 +65,9 @@ extern int dot_symbols;
 
 #define TARGET_USES_LINUX64_OPT 1
 #ifdef HAVE_LD_LARGE_TOC
-extern enum rs6000_cmodel cmodel;
 #undef TARGET_CMODEL
-#define TARGET_CMODEL cmodel
-#define SET_CMODEL(opt) cmodel = opt
+#define TARGET_CMODEL rs6000_current_cmodel
+#define SET_CMODEL(opt) rs6000_current_cmodel = opt
 #else
 #define SET_CMODEL(opt) do {} while (0)
 #endif
@@ -127,7 +126,7 @@ extern enum rs6000_cmodel cmodel;
 	  if ((target_flags_explicit & MASK_MINIMAL_TOC) != 0)	\
 	    {							\
 	      if (rs6000_explicit_options.cmodel		\
-		  && cmodel != CMODEL_SMALL)			\
+		  && rs6000_current_cmodel != CMODEL_SMALL)	\
 		error ("-mcmodel incompatible with other toc options"); \
 	      SET_CMODEL (CMODEL_SMALL);			\
 	    }							\
@@ -135,7 +134,7 @@ extern enum rs6000_cmodel cmodel;
 	    {							\
 	      if (!rs6000_explicit_options.cmodel)		\
 		SET_CMODEL (CMODEL_MEDIUM);			\
-	      if (cmodel != CMODEL_SMALL)			\
+	      if (rs6000_current_cmodel != CMODEL_SMALL)	\
 		{						\
 		  TARGET_NO_FP_IN_TOC = 0;			\
 		  TARGET_NO_SUM_IN_TOC = 0;			\
 gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/ppc-target-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/ppc-target-1.c	(revision 0)
@@ -0,0 +1,59 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ffast-math -mcpu=power5" } */
+/* { dg-final { scan-assembler-times "fabs" 3 } } */
+/* { dg-final { scan-assembler-times "fnabs" 3 } } */
+/* { dg-final { scan-assembler-times "fsel" 3 } } */
+/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
+/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+
+double normal1 (double, double);
+double power5  (double, double) __attribute__((__target__("cpu=power5")));
+double power6  (double, double) __attribute__((__target__("cpu=power6")));
+double power6x (double, double) __attribute__((__target__("cpu=power6x")));
+double power7  (double, double) __attribute__((__target__("cpu=power7")));
+double power7n (double, double) __attribute__((__target__("cpu=power7,no-vsx")));
+double normal2 (double, double);
+
+/* fabs/fnabs/fsel */
+double normal1 (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}
+
+/* fabs/fnabs/fsel */
+double power5  (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power6  (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power6x (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}
+
+/* xscpsgndp */
+double power7  (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power7n (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}
+
+/* fabs/fnabs/fsel */
+double normal2 (double a, double b)
+{
+  return __builtin_copysign (a, b);
+}


More information about the Gcc-patches mailing list