Patchwork Add attribute((target("..."))) and pragma target to PowerPC

login
register
mail settings
Submitter Michael Meissner
Date Oct. 31, 2010, 6:25 p.m.
Message ID <20101031182504.GA14215@hungry-tiger.westford.ibm.com>
Download mbox | patch
Permalink /patch/69732/
State New
Headers show

Comments

Michael Meissner - Oct. 31, 2010, 6:25 p.m.
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.
H.J. Lu - Oct. 31, 2010, 6:31 p.m.
On Sun, Oct 31, 2010 at 11:25 AM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> 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?
>

I don't think we should extend this feature before fixing it properly
on existing
target:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37565
Joseph S. Myers - Oct. 31, 2010, 7:13 p.m.
I'm concerned about the support for a -maltivec function attribute.

As I noted in my comments on the previous patch 
<http://gcc.gnu.org/ml/gcc-patches/2008-08/msg02405.html>, such attributes 
for ABI-affecting options are problematic because of the need to handle 
calls between functions with different ABIs rather than just saving and 
restoring option state.

The problem is that -maltivec is in fact an ABI option.  In some cases - 
conditioned on TARGET_ELF in rs6000_option_override_internal - it implies 
-mabi=altivec; in some cases it may not.  When -mabi=altivec is implied, 
the full AltiVec vector argument passing / return ABI is in effect.  If 
-maltivec -mabi=no-altivec you have a different (broken) ABI - bug 33899 - 
as well as problems with the set of call-clobbered registers - 
<http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00438.html>.

I haven't really tried to figure out whether your patch ensures that 
updating the -maltivec state for a given function also updates the 
-mabi=altivec state and how changes to the call-clobbered register set are 
handled.  But if it doesn't update -mabi=altivec then you get the broken 
combinations, and supposing that it does then you need proper support for 
calls between functions with different ABIs.  The same of course applies 
to -mcpu from target attributes, since -mcpu options affect the AltiVec 
state.
Michael Meissner - Nov. 1, 2010, 4:20 p.m.
On Sun, Oct 31, 2010 at 11:31:51AM -0700, H.J. Lu wrote:
> On Sun, Oct 31, 2010 at 11:25 AM, Michael Meissner
> <meissner@linux.vnet.ibm.com> wrote:
> > 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?
> >
> 
> I don't think we should extend this feature before fixing it properly
> on existing
> target:
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37565

However, I don't think your objection is valid in the case of the PowerPC
patches that I submitted, since these are only target options and not
optimization options.  In fact, I don't modify any optimization options in the
powerpc port within the target option processing, except for the initial
processing of the command line options.

Besides as documented in the bug, TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE is now
available for backends to use if they need to adjust the target options after
the optimizations were changed.  I didn't see it used in the i386 port, but
several other ports now use it.
H.J. Lu - Nov. 1, 2010, 4:23 p.m.
On Mon, Nov 1, 2010 at 9:20 AM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> On Sun, Oct 31, 2010 at 11:31:51AM -0700, H.J. Lu wrote:
>> On Sun, Oct 31, 2010 at 11:25 AM, Michael Meissner
>> <meissner@linux.vnet.ibm.com> wrote:
>> > 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?
>> >
>>
>> I don't think we should extend this feature before fixing it properly
>> on existing
>> target:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37565
>
> However, I don't think your objection is valid in the case of the PowerPC
> patches that I submitted, since these are only target options and not
> optimization options.  In fact, I don't modify any optimization options in the
> powerpc port within the target option processing, except for the initial
> processing of the command line options.
>
> Besides as documented in the bug, TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE is now
> available for backends to use if they need to adjust the target options after
> the optimizations were changed.  I didn't see it used in the i386 port, but
> several other ports now use it.
>

If you exam each bug report closely, you may find
TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
may not solve all problems. Some issues are fundamental, which can't be solved
by one macro.
Michael Meissner - Nov. 1, 2010, 4:28 p.m.
On Mon, Nov 01, 2010 at 09:23:26AM -0700, H.J. Lu wrote:
> If you exam each bug report closely, you may find
> TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
> may not solve all problems. Some issues are fundamental, which can't be solved
> by one macro.

Perhaps, but it still has no bearing on the patches I submitted to add new
features to the PowerPC port.
Michael Meissner - Nov. 1, 2010, 5:49 p.m.
On Sun, Oct 31, 2010 at 07:13:57PM +0000, Joseph S. Myers wrote:
> I'm concerned about the support for a -maltivec function attribute.
> 
> As I noted in my comments on the previous patch 
> <http://gcc.gnu.org/ml/gcc-patches/2008-08/msg02405.html>, such attributes 
> for ABI-affecting options are problematic because of the need to handle 
> calls between functions with different ABIs rather than just saving and 
> restoring option state.
> 
> The problem is that -maltivec is in fact an ABI option.  In some cases - 
> conditioned on TARGET_ELF in rs6000_option_override_internal - it implies 
> -mabi=altivec; in some cases it may not.  When -mabi=altivec is implied, 
> the full AltiVec vector argument passing / return ABI is in effect.  If 
> -maltivec -mabi=no-altivec you have a different (broken) ABI - bug 33899 - 
> as well as problems with the set of call-clobbered registers - 
> <http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00438.html>.

Good point.  I had forgotten, that altivec abi is not set in 32-bit (it is set
in 64-bit mode).  I did not intend to change the ABI in this version of the
patches.

> I haven't really tried to figure out whether your patch ensures that 
> updating the -maltivec state for a given function also updates the 
> -mabi=altivec state and how changes to the call-clobbered register set are 
> handled.  But if it doesn't update -mabi=altivec then you get the broken 
> combinations, and supposing that it does then you need proper support for 
> calls between functions with different ABIs.  The same of course applies 
> to -mcpu from target attributes, since -mcpu options affect the AltiVec 
> state.

The code in rs6000_option_override_internal would set rs6000_altivec_abi if you
switch to power7 or explicitly enable altivec.  That variable is setup to be
switched automatically when you change target contexts with the TargetVariable
option directive, but it doesn't enable the caller to pass things in the AV
registers.

The simplest way to fix this is to require the user on 32-bit to use an
explicit -maltivec-abi switch if they want to switch to a power7 cpu or enable
altivec (similarly for the rs6000_spe_abi, rs6000_float_gprs, and
rs6000_darwin64_abi variables).

However, long term, it may make sense to support calling to different ABI's,
much like the x86 port does, but at this stage, it is probably better to be
safe.

Patch

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) \