This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, committed] Function specific options update


This patch fixes several of the problems with function specific options, and
makes some changes that people were suggested.  I have bootstrapped the
compiler on the x86 and PowerPC architectures, and on the x86 there were no
regressions.  The major changes are:

1) Change 'option' to 'target' in the attribute and pragma, since target is
   much clearer than option.

2) If the target specific option changes the optimization flags (as happens on
   the x86 if you change the cpu being compiled for), the compiler will act as
   if attribute((optimization(...))) was also specified to make sure those
   options are changed.

3) On the x86 delay creating processor specific builtin functions until the
   user compiles for that ISA with either command line options or target
   specific options.  This involved adding a new method in C/C++ to add a
   declaration to the top level scope, even if you were inside of a scope block
   (for other languages without the new hook, the x86 backend adds all of the
   builtin functions at the start of the compilation, when things are
   guaranteed to be at the top level scope).

4) Deletion of the code that changed the optimization options for hot and cold
   functions on the x86 and ia-64.  I also commented out the rules in the
   inliner that prevented cold functions from inlining hot functions, and vice
   versa.  I do think in general, we may want something like this (particularly
   not inlining cold functions), but the code I put in doesn't work.

5) Because of #2, it becomes problematical if the user does #pragma GCC target
   push and then #pragma GCC optimize pop, since target options can now set
   optimization options.  Instead, I added new #pragmas (push_options,
   pop_options, and reset_options) which push both the target specific and
   optimization options.

6) Fix C++ to support target specific options by copying the target and
   optimization attributes when merging declarations.

7) Add a new flag (CL_SAVE) that is set by the Save option flag, to allow
   backends to be able to mark which options are appropriate for target
   specific support, instead of having to have a separate list of options.

2008-08-29  Michael Meissner  <gnu@the-meissners.org>

	* opts.h (CL_SAVE): New option class for marking options that are
	target specific options usable in the target attribute.
	(CL_MIN_OPTION_CLASS): CL_SAVE is now the minimum option.

	* opt-functions.awk (switch_flags): Add CL_SAVE flag so backends
	can easily find the target specific options that are safe to use
	in the attribute or pragma.

	* attribs.c (decl_attributes): Change #pragma GCC option to
	#pragma GCC target, and attribute((option(...))) to
	attribute((target(...))).

	* doc/extend.texi (target attribute): Change from option
	attribute.  Delete push/pop/reset.
	(#pragma GCC target): Change from #pragma GCC option.  Delete
	push/pop/reset.
	(#pragma GCC push_options): Document new pragma.
	(#pragma GCC pop_options): Document new pragma.
	(#pragma GCC reset_options): Document new pragma.

	* targhooks.c (default_target_option_valid_attribute_p): Add
	warning about port not supporting target attributes.
	(default_target_option_pragma_parse): New function, warn about
	#pragma GCC target not being supported.

	* targhooks.h (default_target_option_pragma_parse): Add
	declaration.

	* tree.h (TI_CURRENT_TARGET_PRAGMA): Rename from
	TI_CURRENT_OPTION_PRAGMA.
	(current_target_pragma): Rename from current_option_pragma.

	* target.h: (struct target_option): Delete booleans for changing
	the optimization level on hot/cold functions.  Change signature of
	pragma_parse hook to take a second tree.

	* c-tree.h (c_builtin_function_ext_scope): Add declaration.

	* c-decl.c (c_builtin_function_ext_scope): New function, guarantee
	that the declaration is done at global scope.

	* langhooks.c (add_builtin_function_common): Move most of the code
	from add_builtin_function here, calling the hook passed in.
	(add_builtin_function): Call add_builtin_function_common with
	standard builtin hook.
	(add_builtin_function_ext_scope): New function to add builtins to
	global scope.

	* langhooks.h (struct lang_hooks): Add builtin_function_ext_scope
	hook.
	(add_builtin_function_ext_scope): Add declaration.

	* c-pragma.c (handle_pragma_target): Rename from
	handle_pragma_option, #pragma GCC option is now #pragma GCC
	target.  Move warning about port not supporting target options to
	default pragma parse hook.  Remove push/pop/reset from this
	pragma.
	(handle_pragma_optimize): Remove push/pop/reset from this pragma.
	(option_stack): Delete static variable.
	(optimize_stack): Ditto.
	(optons_stack): New stack of saved target and optimization
	options.
	(handle_pragma_push_options): New function to handle pushing both
	target and optimization options.
	(handle_pragma_pop_options): New function to handle popping both
	target and optimization options.
	(handle_pragma_reset_options): New function to handle resetting
	both target and optimization options to their initial state.
	(init_pragma): Rename handle_pragma_option to
	handle_pragma_target.  Add support for push_options, pop_options,
	and reset_options pragmas.

	* target-def.h (TARGET_OPTION_PRAGMA_PARSE): Change default to
	default_target_option_pragma_parse.
	(TARGET_OPTION_VALID_ATTRIBUTE_P): Change default to
	default_target_option_valid_attribute_p.
	(TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION): Delete.
	(TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION): Ditto.
	(TARGET_OPTION_HOOKS): Delete the fields for whether to change
	optimization level on hot/cold functions.

	* tree-inline.c (tree_can_inline_p): Disable suppressing inlining
	if the caller and callee have different optimization levels.

	* c-common.c (handle_target_attribute): Rename from
	handle_option_attribute, attribute((option(...))) is now
	attribute((target(...))).  Move warning if the port does not
	support target attributes to the default hook.
	(handle_hot_attribute): Delete code to change the optimization
	level of hot functions.
	(handle_cold_attribute): Ditto.

	* config/i386/i386-c.c (ix86_pragma_target_parse): Take a second
	argument that is the binary tree options to use if there are no
	arguments.  Call ix86_valid_target_attribute_tree instead of
	ix86_valid_option_attribute_tree.
	(ix86_pragma_target_parse): Rename from ix86_pragma_option_parse.
	(ix86_register_pragmas): Use ix86_pragma_target_parse instead of
	ix86_pragma_option_parse.

	* config/i386/i386-protos.h (ix86_valid_target_attribute_tree):
	Rename from ix86_valid_option_attribute_tree.

	* config/i386/i386.c (ix86_add_new_builtins): New function to add
	new builtins when the ISA changes.
	(ix86_valid_target_attribute_tree): Rename from
	ix86_valid_option_attribute_tree.  Change callers.  If the
	function specified optimization options, use those as the starting
	point before setting up the target attributes.  If the
	optimization options were changed in the course of setting the
	target attributes, record the new optimization options.
	(ix86_valid_target_attribute_tree_inner_p): Rename from
	ix86_valid_option_attribute_tree_inner_p.  Change callers.  Call
	ix86_add_new_builtins if the ISA changed.
	(ix86_valid_target_attribute_p): Rename from
	ix86_valid_option_attribute_p.  Change callers.
	(enum ix86_builtins): Add IX86_BUILTIN_PCMOV to allow both
	__builtin_ia32_pcmov and __builtin_ia32_pcmov_v2di to be declared
	as delayed builtin functions.
	(struct builtin_isa): New structure to record builtin functions
	that should be delayed until the ISA for that function is used.
	(ix86_builtins_isa): Change from int to struct to track builtin
	functions we want to declare at some point.
	(def_builtin): If the front end can delay defining the builtin
	functions, don't create builtins for ISAs not part of the default
	options.
	(def_builtin_const): Ditto.
	(bdesc_multi_arg): Declare __builtin_ia32_pcmov and
	__builtin_ia32_pcmov_v2di to be different builtin functions.
	(ix86_expand_builtin): Changes due to ix86_builtins_isa now being
	a structure instead of an int.
	(TARGET_OPTION_VALID_ATTRIBUTE_P): Use
	ix86_valid_target_attribute_p, not ix86_valid_option_attribute_p.
	(TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION): Delete.
	(TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION): Ditto.

	* config/ia64/ia64.h
	(TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION): Delete.
	(TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION): Ditto.

	* langhooks-def.h (LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE): New
	hook, default to being the same as LANG_HOOKS_BUILTIN_FUNCTION.
	(LANG_HOOKS_INITIALIZER): Add
	LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE hook.

[gcc/testsuite]
2008-08-29  Michael Meissner  <gnu@the-meissners.org>

	* gcc.target/i386/sse-22.c: Change #pragma GCC option to #pragma
	GCC target.  Change attribute((option(...))) to
	attribute((target(...))).
	* gcc.target/i386/sse-23.c: Ditto.
	* gcc.target/i386/funcspec-1.c: Ditto.
	* gcc.target/i386/funcspec-2.c: Ditto.
	* gcc.target/i386/funcspec-3.c: Ditto.
	* gcc.target/i386/funcspec-4.c: Ditto.
	* gcc.target/i386/funcspec-5.c: Ditto.
	* gcc.target/i386/funcspec-6.c: Ditto.
	* gcc.target/i386/funcspec-7.c: Ditto.
	* gcc.target/i386/funcspec-8.c: Ditto.
	* gcc.target/i386/funcspec-9.c: Ditto.
	* gcc.target/i386/funcspec-10.c: Ditto.
	* gcc.target/i386/funcspec-11.c: Ditto.

	* gcc.target/i386/cold-1.c: Delete.
	* gcc.target/i386/hot-1.c: Ditto.

	* gcc.dg/pr36997.c: Add -msse2 to the target flags.

	* gcc.target/i386/funcspec-8.c: #pragma GCC option push is now
	#pragma GCC push_options, and #pragma GCC option pop is now
	#pragma GCC pop_options.
	* gcc.target/i386/opt-2.c: Ditto.

[gcc/cp]
2008-08-29  Michael Meissner  <gnu@the-meissners.org>

	* decl.c (builtin_function_1): Take a bool argument to decide
	whether to use pushdecl or pushdecl_top_level.
	(duplicate_decls): Copy function specific target and optimization
	options on duplicate declarations.
	(cxx_builtin_function): Update builtin_function_1 call.
	(cxx_builtin_function_ext_scope): New function, guarantee that the
	declaration is done at global scope.

	* cp-objcp-common.h (LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE): New
	macro, define builtin function hook for delayed machine specific
	builtins.

	* cp-tree.h (cxx_builtin_function_ext_scope): Add declaration.

Index: gcc/attribs.c
===================================================================
--- gcc/attribs.c	(revision 139809)
+++ gcc/attribs.c	(working copy)
@@ -252,18 +252,18 @@ decl_attributes (tree *node, tree attrib
       && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
     DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
 
-  /* If this is a function and the user used #pragma GCC option, add the
-     options to the attribute((option(...))) list.  */
+  /* If this is a function and the user used #pragma GCC target, add the
+     options to the attribute((target(...))) list.  */
   if (TREE_CODE (*node) == FUNCTION_DECL
-      && current_option_pragma
+      && current_target_pragma
       && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
-						  current_option_pragma, 0))
+						  current_target_pragma, 0))
     {
-      tree cur_attr = lookup_attribute ("option", attributes);
-      tree opts = copy_list (current_option_pragma);
+      tree cur_attr = lookup_attribute ("target", attributes);
+      tree opts = copy_list (current_target_pragma);
 
       if (! cur_attr)
-	attributes = tree_cons (get_identifier ("option"), opts, attributes);
+	attributes = tree_cons (get_identifier ("target"), opts, attributes);
       else
 	TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
     }
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 139809)
+++ gcc/doc/extend.texi	(working copy)
@@ -2665,19 +2665,19 @@ take function pointer arguments.  The @c
 implemented in GCC versions earlier than 3.3.
 
 @item option
-@cindex @code{option} function attribute
-The @code{option} attribute is used to specify that a function is to
+@cindex @code{target} function attribute
+The @code{target} attribute is used to specify that a function is to
 be compiled with different target options than specified on the
 command line.  This can be used for instance to have functions
 compiled with a different ISA (instruction set architecture) than the
-default.  You can also use the @samp{#pragma GCC option} pragma to set
+default.  You can also use the @samp{#pragma GCC target} pragma to set
 more than one function to be compiled with specific target options.
 @xref{Function Specific Option Pragmas}, for details about the
-@samp{#pragma GCC option} pragma.
+@samp{#pragma GCC target} pragma.
 
 For instance on a 386, you could compile one function with
-@code{option("sse4.1,arch=core2")} and another with
-@code{option("sse4a,arch=amdfam10")} that would be equivalent to
+@code{target("sse4.1,arch=core2")} and another with
+@code{target("sse4a,arch=amdfam10")} that would be equivalent to
 compiling the first function with @option{-msse4.1} and
 @option{-march=core2} options, and the second function with
 @option{-msse4a} and @option{-march=amdfam10} options.  It is up to the
@@ -2687,8 +2687,8 @@ supports the particular ISA it was compi
 family are used).
 
 @smallexample
-int core2_func (void) __attribute__ ((__option__ ("arch=core2")));
-int sse3_func (void) __attribute__ ((__option__ ("sse3")));
+int core2_func (void) __attribute__ ((__target__ ("arch=core2")));
+int sse3_func (void) __attribute__ ((__target__ ("sse3")));
 @end smallexample
 
 On the 386, the following options are allowed:
@@ -2696,132 +2696,132 @@ On the 386, the following options are al
 @table @samp
 @item abm
 @itemx no-abm
-@cindex option("abm")
+@cindex @code{target("abm")} attribute
 Enable/disable the generation of the advanced bit instructions.
 
 @item aes
 @itemx no-aes
-@cindex @code{option("aes")} attribute
+@cindex @code{target("aes")} attribute
 Enable/disable the generation of the AES instructions.
 
 @item mmx
 @itemx no-mmx
-@cindex @code{option("mmx")} attribute
+@cindex @code{target("mmx")} attribute
 Enable/disable the generation of the MMX instructions.
 
 @item pclmul
 @itemx no-pclmul
-@cindex @code{option("pclmul")} attribute
+@cindex @code{target("pclmul")} attribute
 Enable/disable the generation of the PCLMUL instructions.
 
 @item popcnt
 @itemx no-popcnt
-@cindex @code{option("popcnt")} attribute
+@cindex @code{target("popcnt")} attribute
 Enable/disable the generation of the POPCNT instruction.
 
 @item sse
 @itemx no-sse
-@cindex @code{option("sse")} attribute
+@cindex @code{target("sse")} attribute
 Enable/disable the generation of the SSE instructions.
 
 @item sse2
 @itemx no-sse2
-@cindex @code{option("sse2")} attribute
+@cindex @code{target("sse2")} attribute
 Enable/disable the generation of the SSE2 instructions.
 
 @item sse3
 @itemx no-sse3
-@cindex @code{option("sse3")} attribute
+@cindex @code{target("sse3")} attribute
 Enable/disable the generation of the SSE3 instructions.
 
 @item sse4
 @itemx no-sse4
-@cindex @code{option("sse4")} attribute
+@cindex @code{target("sse4")} attribute
 Enable/disable the generation of the SSE4 instructions (both SSE4.1
 and SSE4.2).
 
 @item sse4.1
 @itemx no-sse4.1
-@cindex @code{option("sse4.1")} attribute
+@cindex @code{target("sse4.1")} attribute
 Enable/disable the generation of the sse4.1 instructions.
 
 @item sse4.2
 @itemx no-sse4.2
-@cindex @code{option("sse4.2")} attribute
+@cindex @code{target("sse4.2")} attribute
 Enable/disable the generation of the sse4.2 instructions.
 
 @item sse4a
 @itemx no-sse4a
-@cindex @code{option("sse4a")} attribute
+@cindex @code{target("sse4a")} attribute
 Enable/disable the generation of the SSE4A instructions.
 
 @item sse5
 @itemx no-sse5
-@cindex @code{option("sse5")} attribute
+@cindex @code{target("sse5")} attribute
 Enable/disable the generation of the SSE5 instructions.
 
 @item ssse3
 @itemx no-ssse3
-@cindex @code{option("ssse3")} attribute
+@cindex @code{target("ssse3")} attribute
 Enable/disable the generation of the SSSE3 instructions.
 
 @item cld
 @itemx no-cld
-@cindex @code{option("cld")} attribute
+@cindex @code{target("cld")} attribute
 Enable/disable the generation of the CLD before string moves.
 
 @item fancy-math-387
 @itemx no-fancy-math-387
-@cindex @code{option("fancy-math-387")} attribute
+@cindex @code{target("fancy-math-387")} attribute
 Enable/disable the generation of the @code{sin}, @code{cos}, and
 @code{sqrt} instructions on the 387 floating point unit.
 
 @item fused-madd
 @itemx no-fused-madd
-@cindex @code{option("fused-madd")} attribute
+@cindex @code{target("fused-madd")} attribute
 Enable/disable the generation of the fused multiply/add instructions.
 
 @item ieee-fp
 @itemx no-ieee-fp
-@cindex @code{option("ieee-fp")} attribute
+@cindex @code{target("ieee-fp")} attribute
 Enable/disable the generation of floating point that depends on IEEE arithmetic.
 
 @item inline-all-stringops
 @itemx no-inline-all-stringops
-@cindex @code{option("inline-all-stringops")} attribute
+@cindex @code{target("inline-all-stringops")} attribute
 Enable/disable inlining of string operations.
 
 @item inline-stringops-dynamically
 @itemx no-inline-stringops-dynamically
-@cindex @code{option("inline-stringops-dynamically")} attribute
+@cindex @code{target("inline-stringops-dynamically")} attribute
 Enable/disable the generation of the inline code to do small string
 operations and calling the library routines for large operations.
 
 @item align-stringops
 @itemx no-align-stringops
-@cindex @code{option("align-stringops")} attribute
+@cindex @code{target("align-stringops")} attribute
 Do/do not align destination of inlined string operations.
 
 @item recip
 @itemx no-recip
-@cindex @code{option("recip")} attribute
+@cindex @code{target("recip")} attribute
 Enable/disable the generation of RCPSS, RCPPS, RSQRTSS and RSQRTPS
 instructions followed an additional Newton-Rhapson step instead of
 doing a floating point division.
 
 @item arch=@var{ARCH}
-@cindex @code{option("arch=@var{ARCH}")} attribute
+@cindex @code{target("arch=@var{ARCH}")} attribute
 Specify the architecture to generate code for in compiling the function.
 
 @item tune=@var{TUNE}
-@cindex @code{option("tune=@var{TUNE}")} attribute
+@cindex @code{target("tune=@var{TUNE}")} attribute
 Specify the architecture to tune for in compiling the function.
 
 @item fpmath=@var{FPMATH}
-@cindex @code{option("fpmath=@var{FPMATH}")} attribute
+@cindex @code{target("fpmath=@var{FPMATH}")} attribute
 Specify which floating point unit to use.  The
-@code{option("fpmath=sse,387")} option must be specified as
-@code{option("fpmath=sse+387")} because the comma would separate
+@code{target("fpmath=sse,387")} option must be specified as
+@code{target("fpmath=sse+387")} because the comma would separate
 different options.
 @end table
 
@@ -2831,10 +2831,10 @@ options, or you can separate the option 
 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{option("sse5")} can inline a function with
-@code{option("sse2")}, since @code{-msse5} implies @code{-msse2}.
+@code{target("sse5")} can inline a function with
+@code{target("sse2")}, since @code{-msse5} implies @code{-msse2}.
 
-The @code{option} attribute is not implemented in GCC versions earlier
+The @code{target} attribute is not implemented in GCC versions earlier
 than 4.4, and at present only the 386 uses it.
 
 @item optimize
@@ -2853,17 +2853,7 @@ that affect more than one function.
 This can be used for instance to have frequently executed functions
 compiled with more aggressive optimization options that produce faster
 and larger code, while other functions can be called with less
-aggressive options.  On some targets, the @code{hot} attribute implies
-@code{optimize("O3")}, and @code{cold} attribute implies
-@code{optimize("Os")}.
-
-@smallexample
-int fast_func (void) __attribute__ ((__optimize__ ("O3,unroll-loops")));
-int slow_func (void) __attribute__ ((__optimize__ ("Os")));
-@end smallexample
-
-The inliner will not inline functions with a higher optimization level
-than the caller or different space/time trade offs.
+aggressive options.
 
 @item pure
 @cindex @code{pure} function attribute
@@ -2903,10 +2893,6 @@ are automatically detected and this attr
 The @code{hot} attribute is not implemented in GCC versions earlier
 than 4.3.
 
-Starting with GCC 4.4, the @code{hot} attribute sets
-@code{optimize("O3")} to turn on more aggressive optimization on the
-the i386, x86_64, and IA-64 targets.
-
 @item cold
 @cindex @code{cold} function attribute
 The @code{cold} attribute is used to inform the compiler that a function is
@@ -2924,10 +2910,6 @@ are automatically detected and this attr
 
 The @code{cold} attribute is not implemented in GCC versions earlier than 4.3.
 
-Starting with GCC 4.4, the @code{cold} attribute sets
-@code{optimize("Os")} to save space on the the i386, x86_64, and IA-64
-targets.
-
 @item regparm (@var{number})
 @cindex @code{regparm} attribute
 @cindex functions that are passed arguments in registers on the 386
@@ -11834,42 +11816,23 @@ push_macro} and restored by @code{#pragm
 @subsection Function Specific Option Pragmas
 
 @table @code
-@item #pragma GCC option (@var{"string"}...)
-@cindex pragma GCC option
+@item #pragma GCC target (@var{"string"}...)
+@cindex pragma GCC target
 
 This pragma allows you to set target specific options for functions
 defined later in the source file.  One or more strings can be
 specified.  Each function that is defined after this point will be as
-if @code{attribute((option("STRING")))} was specified for that
+if @code{attribute((target("STRING")))} was specified for that
 function.  The parenthesis around the options is optional.
 @xref{Function Attributes}, for more information about the
-@code{option} attribute and the attribute syntax.
+@code{target} attribute and the attribute syntax.
 
-The @samp{#pragma GCC option} pragma is not implemented in GCC
+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 backend.
+386 and x86_64 backends.
 @end table
 
 @table @code
-@item #pragma GCC option (push)
-@itemx #pragma GCC option (pop)
-@cindex pragma GCC option
-
-These pragmas maintain a stack of the current options.  It is
-intended for include files where you temporarily want to switch to
-using a different @samp{#pragma GCC option} and then to pop back to
-the previous options.
-@end table
-
-@table @code
-@item #pragma GCC option (reset)
-@cindex pragma, target option
-@cindex pragma GCC option
-
-This pragma clears the current @code{#pragma GCC options} to use the
-default switches as specified on the command line.
-@end table
-@table @code
 @item #pragma GCC optimize (@var{"string"}...)
 @cindex pragma GCC optimize
 
@@ -11886,22 +11849,31 @@ versions earlier than 4.4.
 @end table
 
 @table @code
-@item #pragma GCC optimize (push)
-@itemx #pragma GCC optimize (pop)
-@cindex pragma GCC optimize
+@item #pragma GCC push_options
+@itemx #pragma GCC pop_options
+@cindex pragma GCC push_options
+@cindex pragma GCC pop_options
 
-These pragmas maintain a stack of the current optimization options.
-It is intended for include files where you temporarily want to switch
-to using a different @code{#pragma GCC optimize} and then to pop back
-to the previous optimizations.
+These pragmas maintain a stack of the current target and optimization
+options.  It is intended for include files where you temporarily want
+to switch to using a different @samp{#pragma GCC target} or
+@samp{#pragma GCC optimize} and then to pop back to the previous
+options.
+
+The @samp{#pragma GCC push_options} and @samp{#pragma GCC pop_options}
+pragmas are not implemented in GCC versions earlier than 4.4.
 @end table
 
 @table @code
-@item #pragma GCC optimize reset
-@cindex pragma GCC optimize
+@item #pragma GCC reset_options
+@cindex pragma GCC reset_options
 
-This pragma clears the current @code{#pragma GCC optimize} to use the
-default switches as specified on the command line.
+This pragma clears the current @code{#pragma GCC target} and
+@code{#pragma GCC optimize} to use the default switches as specified
+on the command line.
+
+The @samp{#pragma GCC reset_options} pragma is not implemented in GCC
+versions earlier than 4.4.
 @end table
 
 @node Unnamed Fields
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 139809)
+++ gcc/targhooks.c	(working copy)
@@ -715,6 +715,19 @@ default_target_option_valid_attribute_p 
 					 tree ARG_UNUSED (args),
 					 int ARG_UNUSED (flags))
 {
+  warning (OPT_Wattributes,
+	   "target attribute is not supported on this machine");
+
+  return false;
+}
+
+bool
+default_target_option_pragma_parse (tree ARG_UNUSED (args),
+				    tree ARG_UNUSED (pop_target))
+{
+  warning (OPT_Wpragmas,
+	   "#pragma GCC target is not supported for this machine");
+
   return false;
 }
 
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(revision 139809)
+++ gcc/targhooks.h	(working copy)
@@ -99,4 +99,5 @@ extern tree default_emutls_var_fields (t
 extern tree default_emutls_var_init (tree, tree, tree);
 extern bool default_hard_regno_scratch_ok (unsigned int);
 extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
+extern bool default_target_option_pragma_parse (tree, tree);
 extern bool default_target_option_can_inline_p (tree, tree);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 139809)
+++ gcc/tree.h	(working copy)
@@ -3591,11 +3591,9 @@ enum tree_index
 
   TI_OPTIMIZATION_DEFAULT,
   TI_OPTIMIZATION_CURRENT,
-  TI_OPTIMIZATION_COLD,
-  TI_OPTIMIZATION_HOT,
   TI_TARGET_OPTION_DEFAULT,
   TI_TARGET_OPTION_CURRENT,
-  TI_CURRENT_OPTION_PRAGMA,
+  TI_CURRENT_TARGET_PRAGMA,
   TI_CURRENT_OPTIMIZE_PRAGMA,
 
   TI_MAX
@@ -3765,12 +3763,10 @@ extern GTY(()) tree global_trees[TI_MAX]
 #define main_identifier_node		global_trees[TI_MAIN_IDENTIFIER]
 #define MAIN_NAME_P(NODE) (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node)
 
-/* Optimization options (OPTIMIZATION_NODE) to use for default, current, cold,
-   and hot functions.  */
+/* Optimization options (OPTIMIZATION_NODE) to use for default and current
+   functions.  */
 #define optimization_default_node	global_trees[TI_OPTIMIZATION_DEFAULT]
 #define optimization_current_node	global_trees[TI_OPTIMIZATION_CURRENT]
-#define optimization_cold_node		global_trees[TI_OPTIMIZATION_COLD]
-#define optimization_hot_node		global_trees[TI_OPTIMIZATION_HOT]
 
 /* Default/current target options (TARGET_OPTION_NODE).  */
 #define target_option_default_node	global_trees[TI_TARGET_OPTION_DEFAULT]
@@ -3778,7 +3774,7 @@ extern GTY(()) tree global_trees[TI_MAX]
 
 /* Default tree list option(), optimize() pragmas to be linked into the
    attribute list.  */
-#define current_option_pragma		global_trees[TI_CURRENT_OPTION_PRAGMA]
+#define current_target_pragma		global_trees[TI_CURRENT_TARGET_PRAGMA]
 #define current_optimize_pragma		global_trees[TI_CURRENT_OPTIMIZE_PRAGMA]
 
 /* An enumeration of the standard C integer types.  These must be
Index: gcc/target.h
===================================================================
--- gcc/target.h	(revision 139809)
+++ gcc/target.h	(working copy)
@@ -991,19 +991,13 @@ struct gcc_target
     void (*print) (FILE *, int, struct cl_target_option *);
 
     /* Function to parse arguments to be validated for #pragma option, and to
-       change the state if the options are valid.  If the arguments are NULL,
-       use the default target options.  Return true if the options are valid,
-       and set the current state.  */
-    bool (*pragma_parse) (tree);
+       change the state if the options are valid.  If the first argument is
+       NULL, the second argument specifies the default options to use.  Return
+       true if the options are valid, and set the current state.  */
+    bool (*pragma_parse) (tree, tree);
 
     /* Function to determine if one function can inline another function.  */
     bool (*can_inline_p) (tree, tree);
-
-    /* Whether the cold attribute changes the optimization level.  */
-    bool cold_attribute_sets_optimization;
-
-    /* Whether the hot attribute changes the optimization level.  */
-    bool hot_attribute_sets_optimization;
   } target_option;
 
   /* For targets that need to mark extra registers as live on entry to
Index: gcc/testsuite/gcc.target/i386/opt-2.c
===================================================================
--- gcc/testsuite/gcc.target/i386/opt-2.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/opt-2.c	(working copy)
@@ -12,7 +12,7 @@ float b[SIZE] __attribute__((__aligned__
 float c[SIZE] __attribute__((__aligned__(32)));
 
 /* This should vectorize.  */
-#pragma GCC optimize push
+#pragma GCC push_options
 #pragma GCC optimize (3, "unroll-all-loops", "-fprefetch-loop-arrays")
 
 void
@@ -24,7 +24,7 @@ opt3 (void)
     a[i] = b[i] + c[i];
 }
 
-#pragma GCC optimize pop
+#pragma GCC pop_options
 
 /* This should not vectorize.  */
 void
Index: gcc/testsuite/gcc.target/i386/funcspec-11.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-11.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-11.c	(working copy)
@@ -4,7 +4,7 @@
 /* { dg-options "-O2 -march=i386" } */
 /* { dg-final { scan-assembler "cmov" } } */
 
-extern int foo (int) __attribute__((__option__("arch=i686")));
+extern int foo (int) __attribute__((__target__("arch=i686")));
 
 int
 foo (int x)
Index: gcc/testsuite/gcc.target/i386/funcspec-2.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-2.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-2.c	(working copy)
@@ -5,7 +5,7 @@
 
 extern void exit (int);
 
-#define SSE5_ATTR __attribute__((__option__("sse5,fused-madd")))
+#define SSE5_ATTR __attribute__((__target__("sse5,fused-madd")))
 extern float  flt_mul_add     (float a, float b, float c) SSE5_ATTR;
 extern float  flt_mul_sub     (float a, float b, float c) SSE5_ATTR;
 extern float  flt_neg_mul_add (float a, float b, float c) SSE5_ATTR;
Index: gcc/testsuite/gcc.target/i386/funcspec-4.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-4.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-4.c	(working copy)
@@ -2,13 +2,13 @@
 /* { dg-do compile } */
 
 /* no sse500 switch */
-extern void error1 (void) __attribute__((__option__("sse500"))); /* { dg-error "unknown" } */
+extern void error1 (void) __attribute__((__target__("sse500"))); /* { dg-error "unknown" } */
 
 /* Multiple arch switches */
-extern void error2 (void) __attribute__((__option__("arch=core2,arch=k8"))); /* { dg-error "already specified" } */
+extern void error2 (void) __attribute__((__target__("arch=core2,arch=k8"))); /* { dg-error "already specified" } */
 
 /* Unknown tune target */
-extern void error3 (void) __attribute__((__option__("tune=foobar"))); /* { dg-error "bad value" } */
+extern void error3 (void) __attribute__((__target__("tune=foobar"))); /* { dg-error "bad value" } */
 
 /* option on a variable */
-extern int error4 __attribute__((__option__("sse2"))); /* { dg-warning "ignored" } */
+extern int error4 __attribute__((__target__("sse2"))); /* { dg-warning "ignored" } */
Index: gcc/testsuite/gcc.target/i386/hot-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/hot-1.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/hot-1.c	(working copy)
@@ -1,33 +0,0 @@
-/* Test whether using attribute((hot)) really turns on -O3.  Do this test
-   by checking whether we vectorize a simple loop.  */
-/* { dg-do compile } */
-/* { dg-options "-O1 -msse2 -mfpmath=sse -march=k8" } */
-/* { dg-final { scan-assembler "addps" } } */
-/* { dg-final { scan-assembler "subss" } } */
-
-#define SIZE 1024
-float a[SIZE] __attribute__((__aligned__(32)));
-float b[SIZE] __attribute__((__aligned__(32)));
-float c[SIZE] __attribute__((__aligned__(32)));
-
-/* This should vectorize.  */
-void hot (void) __attribute__((__hot__));
-
-void
-hot (void)
-{
-  int i;
-
-  for (i = 0; i < SIZE; i++)
-    a[i] = b[i] + c[i];
-}
-
-/* This should not vectorize.  */
-void
-not_hot (void)
-{
-  int i;
-
-  for (i = 0; i < SIZE; i++)
-    a[i] = b[i] - c[i];
-}
Index: gcc/testsuite/gcc.target/i386/funcspec-6.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-6.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-6.c	(working copy)
@@ -3,69 +3,69 @@
 /* { dg-do compile } */
 /* { dg-require-effective-target lp64 } */
 
-extern void test_abm (void)			__attribute__((__option__("abm")));
-extern void test_aes (void)			__attribute__((__option__("aes")));
-extern void test_fused_madd (void)		__attribute__((__option__("fused-madd")));
-extern void test_mmx (void)			__attribute__((__option__("mmx")));
-extern void test_pclmul (void)			__attribute__((__option__("pclmul")));
-extern void test_popcnt (void)			__attribute__((__option__("popcnt")));
-extern void test_recip (void)			__attribute__((__option__("recip")));
-extern void test_sse (void)			__attribute__((__option__("sse")));
-extern void test_sse2 (void)			__attribute__((__option__("sse2")));
-extern void test_sse3 (void)			__attribute__((__option__("sse3")));
-extern void test_sse4 (void)			__attribute__((__option__("sse4")));
-extern void test_sse4_1 (void)			__attribute__((__option__("sse4.1")));
-extern void test_sse4_2 (void)			__attribute__((__option__("sse4.2")));
-extern void test_sse4a (void)			__attribute__((__option__("sse4a")));
-extern void test_sse5 (void)			__attribute__((__option__("sse5")));
-extern void test_ssse3 (void)			__attribute__((__option__("ssse3")));
+extern void test_abm (void)			__attribute__((__target__("abm")));
+extern void test_aes (void)			__attribute__((__target__("aes")));
+extern void test_fused_madd (void)		__attribute__((__target__("fused-madd")));
+extern void test_mmx (void)			__attribute__((__target__("mmx")));
+extern void test_pclmul (void)			__attribute__((__target__("pclmul")));
+extern void test_popcnt (void)			__attribute__((__target__("popcnt")));
+extern void test_recip (void)			__attribute__((__target__("recip")));
+extern void test_sse (void)			__attribute__((__target__("sse")));
+extern void test_sse2 (void)			__attribute__((__target__("sse2")));
+extern void test_sse3 (void)			__attribute__((__target__("sse3")));
+extern void test_sse4 (void)			__attribute__((__target__("sse4")));
+extern void test_sse4_1 (void)			__attribute__((__target__("sse4.1")));
+extern void test_sse4_2 (void)			__attribute__((__target__("sse4.2")));
+extern void test_sse4a (void)			__attribute__((__target__("sse4a")));
+extern void test_sse5 (void)			__attribute__((__target__("sse5")));
+extern void test_ssse3 (void)			__attribute__((__target__("ssse3")));
 
-extern void test_no_abm (void)			__attribute__((__option__("no-abm")));
-extern void test_no_aes (void)			__attribute__((__option__("no-aes")));
-extern void test_no_fused_madd (void)		__attribute__((__option__("no-fused-madd")));
-extern void test_no_mmx (void)			__attribute__((__option__("no-mmx")));
-extern void test_no_pclmul (void)		__attribute__((__option__("no-pclmul")));
-extern void test_no_popcnt (void)		__attribute__((__option__("no-popcnt")));
-extern void test_no_recip (void)		__attribute__((__option__("no-recip")));
-extern void test_no_sse (void)			__attribute__((__option__("no-sse")));
-extern void test_no_sse2 (void)			__attribute__((__option__("no-sse2")));
-extern void test_no_sse3 (void)			__attribute__((__option__("no-sse3")));
-extern void test_no_sse4 (void)			__attribute__((__option__("no-sse4")));
-extern void test_no_sse4_1 (void)		__attribute__((__option__("no-sse4.1")));
-extern void test_no_sse4_2 (void)		__attribute__((__option__("no-sse4.2")));
-extern void test_no_sse4a (void)		__attribute__((__option__("no-sse4a")));
-extern void test_no_sse5 (void)			__attribute__((__option__("no-sse5")));
-extern void test_no_ssse3 (void)		__attribute__((__option__("no-ssse3")));
+extern void test_no_abm (void)			__attribute__((__target__("no-abm")));
+extern void test_no_aes (void)			__attribute__((__target__("no-aes")));
+extern void test_no_fused_madd (void)		__attribute__((__target__("no-fused-madd")));
+extern void test_no_mmx (void)			__attribute__((__target__("no-mmx")));
+extern void test_no_pclmul (void)		__attribute__((__target__("no-pclmul")));
+extern void test_no_popcnt (void)		__attribute__((__target__("no-popcnt")));
+extern void test_no_recip (void)		__attribute__((__target__("no-recip")));
+extern void test_no_sse (void)			__attribute__((__target__("no-sse")));
+extern void test_no_sse2 (void)			__attribute__((__target__("no-sse2")));
+extern void test_no_sse3 (void)			__attribute__((__target__("no-sse3")));
+extern void test_no_sse4 (void)			__attribute__((__target__("no-sse4")));
+extern void test_no_sse4_1 (void)		__attribute__((__target__("no-sse4.1")));
+extern void test_no_sse4_2 (void)		__attribute__((__target__("no-sse4.2")));
+extern void test_no_sse4a (void)		__attribute__((__target__("no-sse4a")));
+extern void test_no_sse5 (void)			__attribute__((__target__("no-sse5")));
+extern void test_no_ssse3 (void)		__attribute__((__target__("no-ssse3")));
 
-extern void test_arch_nocona (void)		__attribute__((__option__("arch=nocona")));
-extern void test_arch_core2 (void)		__attribute__((__option__("arch=core2")));
-extern void test_arch_k8 (void)			__attribute__((__option__("arch=k8")));
-extern void test_arch_k8_sse3 (void)		__attribute__((__option__("arch=k8-sse3")));
-extern void test_arch_opteron (void)		__attribute__((__option__("arch=opteron")));
-extern void test_arch_opteron_sse3 (void)	__attribute__((__option__("arch=opteron-sse3")));
-extern void test_arch_athlon64 (void)		__attribute__((__option__("arch=athlon64")));
-extern void test_arch_athlon64_sse3 (void)	__attribute__((__option__("arch=athlon64-sse3")));
-extern void test_arch_athlon_fx (void)		__attribute__((__option__("arch=athlon-fx")));
-extern void test_arch_amdfam10 (void)		__attribute__((__option__("arch=amdfam10")));
-extern void test_arch_barcelona (void)		__attribute__((__option__("arch=barcelona")));
-extern void test_arch_foo (void)		__attribute__((__option__("arch=foo"))); /* { dg-error "bad value" } */
+extern void test_arch_nocona (void)		__attribute__((__target__("arch=nocona")));
+extern void test_arch_core2 (void)		__attribute__((__target__("arch=core2")));
+extern void test_arch_k8 (void)			__attribute__((__target__("arch=k8")));
+extern void test_arch_k8_sse3 (void)		__attribute__((__target__("arch=k8-sse3")));
+extern void test_arch_opteron (void)		__attribute__((__target__("arch=opteron")));
+extern void test_arch_opteron_sse3 (void)	__attribute__((__target__("arch=opteron-sse3")));
+extern void test_arch_athlon64 (void)		__attribute__((__target__("arch=athlon64")));
+extern void test_arch_athlon64_sse3 (void)	__attribute__((__target__("arch=athlon64-sse3")));
+extern void test_arch_athlon_fx (void)		__attribute__((__target__("arch=athlon-fx")));
+extern void test_arch_amdfam10 (void)		__attribute__((__target__("arch=amdfam10")));
+extern void test_arch_barcelona (void)		__attribute__((__target__("arch=barcelona")));
+extern void test_arch_foo (void)		__attribute__((__target__("arch=foo"))); /* { dg-error "bad value" } */
 
-extern void test_tune_nocona (void)		__attribute__((__option__("tune=nocona")));
-extern void test_tune_core2 (void)		__attribute__((__option__("tune=core2")));
-extern void test_tune_k8 (void)			__attribute__((__option__("tune=k8")));
-extern void test_tune_k8_sse3 (void)		__attribute__((__option__("tune=k8-sse3")));
-extern void test_tune_opteron (void)		__attribute__((__option__("tune=opteron")));
-extern void test_tune_opteron_sse3 (void)	__attribute__((__option__("tune=opteron-sse3")));
-extern void test_tune_athlon64 (void)		__attribute__((__option__("tune=athlon64")));
-extern void test_tune_athlon64_sse3 (void)	__attribute__((__option__("tune=athlon64-sse3")));
-extern void test_tune_athlon_fx (void)		__attribute__((__option__("tune=athlon-fx")));
-extern void test_tune_amdfam10 (void)		__attribute__((__option__("tune=amdfam10")));
-extern void test_tune_barcelona (void)		__attribute__((__option__("tune=barcelona")));
-extern void test_tune_generic (void)		__attribute__((__option__("tune=generic")));
-extern void test_tune_foo (void)		__attribute__((__option__("tune=foo"))); /* { dg-error "bad value" } */
+extern void test_tune_nocona (void)		__attribute__((__target__("tune=nocona")));
+extern void test_tune_core2 (void)		__attribute__((__target__("tune=core2")));
+extern void test_tune_k8 (void)			__attribute__((__target__("tune=k8")));
+extern void test_tune_k8_sse3 (void)		__attribute__((__target__("tune=k8-sse3")));
+extern void test_tune_opteron (void)		__attribute__((__target__("tune=opteron")));
+extern void test_tune_opteron_sse3 (void)	__attribute__((__target__("tune=opteron-sse3")));
+extern void test_tune_athlon64 (void)		__attribute__((__target__("tune=athlon64")));
+extern void test_tune_athlon64_sse3 (void)	__attribute__((__target__("tune=athlon64-sse3")));
+extern void test_tune_athlon_fx (void)		__attribute__((__target__("tune=athlon-fx")));
+extern void test_tune_amdfam10 (void)		__attribute__((__target__("tune=amdfam10")));
+extern void test_tune_barcelona (void)		__attribute__((__target__("tune=barcelona")));
+extern void test_tune_generic (void)		__attribute__((__target__("tune=generic")));
+extern void test_tune_foo (void)		__attribute__((__target__("tune=foo"))); /* { dg-error "bad value" } */
 
-extern void test_fpmath_sse (void)		__attribute__((__option__("sse2,fpmath=sse")));
-extern void test_fpmath_387 (void)		__attribute__((__option__("sse2,fpmath=387")));
-extern void test_fpmath_sse_387 (void)		__attribute__((__option__("sse2,fpmath=sse+387")));
-extern void test_fpmath_387_sse (void)		__attribute__((__option__("sse2,fpmath=387+sse")));
-extern void test_fpmath_both (void)		__attribute__((__option__("sse2,fpmath=both")));
+extern void test_fpmath_sse (void)		__attribute__((__target__("sse2,fpmath=sse")));
+extern void test_fpmath_387 (void)		__attribute__((__target__("sse2,fpmath=387")));
+extern void test_fpmath_sse_387 (void)		__attribute__((__target__("sse2,fpmath=sse+387")));
+extern void test_fpmath_387_sse (void)		__attribute__((__target__("sse2,fpmath=387+sse")));
+extern void test_fpmath_both (void)		__attribute__((__target__("sse2,fpmath=both")));
Index: gcc/testsuite/gcc.target/i386/funcspec-8.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-8.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-8.c	(working copy)
@@ -12,7 +12,7 @@ typedef long long __m128i __attribute__ 
 #error "-msse3 should not be set for this test"
 #endif
 
-__m128d sse3_hsubpd (__m128d a, __m128d b) __attribute__((__option__("sse3")));
+__m128d sse3_hsubpd (__m128d a, __m128d b) __attribute__((__target__("sse3")));
 __m128d generic_hsubpd (__m128d a, __m128d b);
 
 __m128d
@@ -31,7 +31,7 @@ generic_hsubpd (__m128d a, __m128d b)
 #error "-mssse3 should not be set for this test"
 #endif
 
-__m128w ssse3_psignd128 (__m128w a, __m128w b) __attribute__((__option__("ssse3")));
+__m128w ssse3_psignd128 (__m128w a, __m128w b) __attribute__((__target__("ssse3")));
 __m128w generic_psignd (__m128w ab, __m128w b);
 
 __m128w
@@ -50,7 +50,7 @@ generic_psignd128 (__m128w a, __m128w b)
 #error "-msse4.1 should not be set for this test"
 #endif
 
-__m128d sse4_1_blendvpd (__m128d a, __m128d b, __m128d c) __attribute__((__option__("sse4.1")));
+__m128d sse4_1_blendvpd (__m128d a, __m128d b, __m128d c) __attribute__((__target__("sse4.1")));
 __m128d generic_blendvpd (__m128d a, __m128d b, __m128d c);
 
 __m128d
@@ -69,7 +69,7 @@ generic_blendvpd  (__m128d a, __m128d b,
 #error "-msse4.2 should not be set for this test"
 #endif
 
-__m128i sse4_2_pcmpgtq (__m128i a, __m128i b) __attribute__((__option__("sse4.2")));
+__m128i sse4_2_pcmpgtq (__m128i a, __m128i b) __attribute__((__target__("sse4.2")));
 __m128i generic_pcmpgtq (__m128i ab, __m128i b);
 
 __m128i
@@ -88,7 +88,7 @@ generic_pcmpgtq (__m128i a, __m128i b)
 #error "-msse4a should not be set for this test"
 #endif
 
-__m128i sse4_2_insertq (__m128i a, __m128i b) __attribute__((__option__("sse4a")));
+__m128i sse4_2_insertq (__m128i a, __m128i b) __attribute__((__target__("sse4a")));
 __m128i generic_insertq (__m128i ab, __m128i b);
 
 __m128i
@@ -107,7 +107,7 @@ generic_insertq (__m128i a, __m128i b)
 #error "-msse5 should not be set for this test"
 #endif
 
-__m128d sse5_fmaddpd (__m128d a, __m128d b, __m128d c) __attribute__((__option__("sse5")));
+__m128d sse5_fmaddpd (__m128d a, __m128d b, __m128d c) __attribute__((__target__("sse5")));
 __m128d generic_fmaddpd (__m128d a, __m128d b, __m128d c);
 
 __m128d
@@ -126,7 +126,7 @@ generic_fmaddpd  (__m128d a, __m128d b, 
 #error "-maes should not be set for this test"
 #endif
 
-__m128i aes_aesimc128 (__m128i a) __attribute__((__option__("aes")));
+__m128i aes_aesimc128 (__m128i a) __attribute__((__target__("aes")));
 __m128i generic_aesimc128 (__m128i a);
 
 __m128i
@@ -145,7 +145,7 @@ generic_aesimc128 (__m128i a)
 #error "-mpclmul should not be set for this test"
 #endif
 
-__m128i pclmul_pclmulqdq128 (__m128i a, __m128i b) __attribute__((__option__("pclmul")));
+__m128i pclmul_pclmulqdq128 (__m128i a, __m128i b) __attribute__((__target__("pclmul")));
 __m128i generic_pclmulqdq128 (__m128i a, __m128i b);
 
 __m128i
Index: gcc/testsuite/gcc.target/i386/sse-23.c
===================================================================
--- gcc/testsuite/gcc.target/i386/sse-23.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/sse-23.c	(working copy)
@@ -101,7 +101,7 @@
 #define __builtin_ia32_protqi(A, B) __builtin_ia32_protqi(A,1)
 
 
-#pragma GCC option ("3dnow,sse4,sse5,aes,pclmul")
+#pragma GCC target ("3dnow,sse4,sse5,aes,pclmul")
 #include <wmmintrin.h>
 #include <bmmintrin.h>
 #include <smmintrin.h>
Index: gcc/testsuite/gcc.target/i386/funcspec-10.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-10.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-10.c	(working copy)
@@ -4,7 +4,7 @@
 /* { dg-options "-O2 -march=i686" } */
 /* { dg-final { scan-assembler-not "cmov" } } */
 
-extern int foo (int) __attribute__((__option__("arch=i386")));
+extern int foo (int) __attribute__((__target__("arch=i386")));
 
 int
 foo (int x)
Index: gcc/testsuite/gcc.target/i386/cold-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/cold-1.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/cold-1.c	(working copy)
@@ -1,13 +0,0 @@
-/* Test whether using attribute((cold)) really turns on -Os.  Do this test
-   by checking whether strcpy calls the library function rather than doing
-   the move inline.  */
-/* { dg-do compile } */
-/* { dg-options "-O3 -march=k8" } */
-/* { dg-final { scan-assembler "(jmp|call)\t(.*)strcpy" } } */
-
-void cold (char *) __attribute__((__cold__));
-
-void cold (char *a)
-{
-  __builtin_strcpy (a, "testing 1.2.3 testing 1.2.3");
-}
Index: gcc/testsuite/gcc.target/i386/funcspec-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-1.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-1.c	(working copy)
@@ -15,7 +15,7 @@ static float a[SIZE] __attribute__((__al
 static float b[SIZE] __attribute__((__aligned__(16)));
 static float c[SIZE] __attribute__((__aligned__(16)));
 
-void sse_addnums (void) __attribute__ ((__option__ ("sse2")));
+void sse_addnums (void) __attribute__ ((__target__ ("sse2")));
 
 void
 sse_addnums (void)
Index: gcc/testsuite/gcc.target/i386/funcspec-3.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-3.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-3.c	(working copy)
@@ -7,8 +7,8 @@
 extern void exit (int);
 extern void abort (void);
 
-#define SSE4A_ATTR __attribute__((__option__("arch=amdfam10")))
-#define SSE42_ATTR __attribute__((__option__("sse4.2")))
+#define SSE4A_ATTR __attribute__((__target__("arch=amdfam10")))
+#define SSE42_ATTR __attribute__((__target__("sse4.2")))
 
 static int sse4a_pop_i (int a) SSE4A_ATTR;
 static long sse42_pop_l (long a) SSE42_ATTR;
Index: gcc/testsuite/gcc.target/i386/funcspec-5.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-5.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-5.c	(working copy)
@@ -3,123 +3,123 @@
 /* { dg-do compile } */
 /* { dg-require-effective-target ilp32 } */
 
-extern void test_abm (void)			__attribute__((__option__("abm")));
-extern void test_aes (void)			__attribute__((__option__("aes")));
-extern void test_fused_madd (void)		__attribute__((__option__("fused-madd")));
-extern void test_mmx (void)			__attribute__((__option__("mmx")));
-extern void test_pclmul (void)			__attribute__((__option__("pclmul")));
-extern void test_popcnt (void)			__attribute__((__option__("popcnt")));
-extern void test_recip (void)			__attribute__((__option__("recip")));
-extern void test_sse (void)			__attribute__((__option__("sse")));
-extern void test_sse2 (void)			__attribute__((__option__("sse2")));
-extern void test_sse3 (void)			__attribute__((__option__("sse3")));
-extern void test_sse4 (void)			__attribute__((__option__("sse4")));
-extern void test_sse4_1 (void)			__attribute__((__option__("sse4.1")));
-extern void test_sse4_2 (void)			__attribute__((__option__("sse4.2")));
-extern void test_sse4a (void)			__attribute__((__option__("sse4a")));
-extern void test_sse5 (void)			__attribute__((__option__("sse5")));
-extern void test_ssse3 (void)			__attribute__((__option__("ssse3")));
+extern void test_abm (void)			__attribute__((__target__("abm")));
+extern void test_aes (void)			__attribute__((__target__("aes")));
+extern void test_fused_madd (void)		__attribute__((__target__("fused-madd")));
+extern void test_mmx (void)			__attribute__((__target__("mmx")));
+extern void test_pclmul (void)			__attribute__((__target__("pclmul")));
+extern void test_popcnt (void)			__attribute__((__target__("popcnt")));
+extern void test_recip (void)			__attribute__((__target__("recip")));
+extern void test_sse (void)			__attribute__((__target__("sse")));
+extern void test_sse2 (void)			__attribute__((__target__("sse2")));
+extern void test_sse3 (void)			__attribute__((__target__("sse3")));
+extern void test_sse4 (void)			__attribute__((__target__("sse4")));
+extern void test_sse4_1 (void)			__attribute__((__target__("sse4.1")));
+extern void test_sse4_2 (void)			__attribute__((__target__("sse4.2")));
+extern void test_sse4a (void)			__attribute__((__target__("sse4a")));
+extern void test_sse5 (void)			__attribute__((__target__("sse5")));
+extern void test_ssse3 (void)			__attribute__((__target__("ssse3")));
 
-extern void test_no_abm (void)			__attribute__((__option__("no-abm")));
-extern void test_no_aes (void)			__attribute__((__option__("no-aes")));
-extern void test_no_fused_madd (void)		__attribute__((__option__("no-fused-madd")));
-extern void test_no_mmx (void)			__attribute__((__option__("no-mmx")));
-extern void test_no_pclmul (void)		__attribute__((__option__("no-pclmul")));
-extern void test_no_popcnt (void)		__attribute__((__option__("no-popcnt")));
-extern void test_no_recip (void)		__attribute__((__option__("no-recip")));
-extern void test_no_sse (void)			__attribute__((__option__("no-sse")));
-extern void test_no_sse2 (void)			__attribute__((__option__("no-sse2")));
-extern void test_no_sse3 (void)			__attribute__((__option__("no-sse3")));
-extern void test_no_sse4 (void)			__attribute__((__option__("no-sse4")));
-extern void test_no_sse4_1 (void)		__attribute__((__option__("no-sse4.1")));
-extern void test_no_sse4_2 (void)		__attribute__((__option__("no-sse4.2")));
-extern void test_no_sse4a (void)		__attribute__((__option__("no-sse4a")));
-extern void test_no_sse5 (void)			__attribute__((__option__("no-sse5")));
-extern void test_no_ssse3 (void)		__attribute__((__option__("no-ssse3")));
+extern void test_no_abm (void)			__attribute__((__target__("no-abm")));
+extern void test_no_aes (void)			__attribute__((__target__("no-aes")));
+extern void test_no_fused_madd (void)		__attribute__((__target__("no-fused-madd")));
+extern void test_no_mmx (void)			__attribute__((__target__("no-mmx")));
+extern void test_no_pclmul (void)		__attribute__((__target__("no-pclmul")));
+extern void test_no_popcnt (void)		__attribute__((__target__("no-popcnt")));
+extern void test_no_recip (void)		__attribute__((__target__("no-recip")));
+extern void test_no_sse (void)			__attribute__((__target__("no-sse")));
+extern void test_no_sse2 (void)			__attribute__((__target__("no-sse2")));
+extern void test_no_sse3 (void)			__attribute__((__target__("no-sse3")));
+extern void test_no_sse4 (void)			__attribute__((__target__("no-sse4")));
+extern void test_no_sse4_1 (void)		__attribute__((__target__("no-sse4.1")));
+extern void test_no_sse4_2 (void)		__attribute__((__target__("no-sse4.2")));
+extern void test_no_sse4a (void)		__attribute__((__target__("no-sse4a")));
+extern void test_no_sse5 (void)			__attribute__((__target__("no-sse5")));
+extern void test_no_ssse3 (void)		__attribute__((__target__("no-ssse3")));
 
-extern void test_arch_i386 (void)		__attribute__((__option__("arch=i386")));
-extern void test_arch_i486 (void)		__attribute__((__option__("arch=i486")));
-extern void test_arch_i586 (void)		__attribute__((__option__("arch=i586")));
-extern void test_arch_pentium (void)		__attribute__((__option__("arch=pentium")));
-extern void test_arch_pentium_mmx (void)	__attribute__((__option__("arch=pentium-mmx")));
-extern void test_arch_winchip_c6 (void)		__attribute__((__option__("arch=winchip-c6")));
-extern void test_arch_winchip2 (void)		__attribute__((__option__("arch=winchip2")));
-extern void test_arch_c3 (void)			__attribute__((__option__("arch=c3")));
-extern void test_arch_c3_2 (void)		__attribute__((__option__("arch=c3-2")));
-extern void test_arch_i686 (void)		__attribute__((__option__("arch=i686")));
-extern void test_arch_pentiumpro (void)		__attribute__((__option__("arch=pentiumpro")));
-extern void test_arch_pentium2 (void)		__attribute__((__option__("arch=pentium2")));
-extern void test_arch_pentium3 (void)		__attribute__((__option__("arch=pentium3")));
-extern void test_arch_pentium3m (void)		__attribute__((__option__("arch=pentium3m")));
-extern void test_arch_pentium_m (void)		__attribute__((__option__("arch=pentium-m")));
-extern void test_arch_pentium4 (void)		__attribute__((__option__("arch=pentium4")));
-extern void test_arch_pentium4m (void)		__attribute__((__option__("arch=pentium4m")));
-extern void test_arch_prescott (void)		__attribute__((__option__("arch=prescott")));
-extern void test_arch_nocona (void)		__attribute__((__option__("arch=nocona")));
-extern void test_arch_core2 (void)		__attribute__((__option__("arch=core2")));
-extern void test_arch_geode (void)		__attribute__((__option__("arch=geode")));
-extern void test_arch_k6 (void)			__attribute__((__option__("arch=k6")));
-extern void test_arch_k6_2 (void)		__attribute__((__option__("arch=k6-2")));
-extern void test_arch_k6_3 (void)		__attribute__((__option__("arch=k6-3")));
-extern void test_arch_athlon (void)		__attribute__((__option__("arch=athlon")));
-extern void test_arch_athlon_tbird (void)	__attribute__((__option__("arch=athlon-tbird")));
-extern void test_arch_athlon_4 (void)		__attribute__((__option__("arch=athlon-4")));
-extern void test_arch_athlon_xp (void)		__attribute__((__option__("arch=athlon-xp")));
-extern void test_arch_athlon_mp (void)		__attribute__((__option__("arch=athlon-mp")));
-extern void test_arch_k8 (void)			__attribute__((__option__("arch=k8")));
-extern void test_arch_k8_sse3 (void)		__attribute__((__option__("arch=k8-sse3")));
-extern void test_arch_opteron (void)		__attribute__((__option__("arch=opteron")));
-extern void test_arch_opteron_sse3 (void)	__attribute__((__option__("arch=opteron-sse3")));
-extern void test_arch_athlon64 (void)		__attribute__((__option__("arch=athlon64")));
-extern void test_arch_athlon64_sse3 (void)	__attribute__((__option__("arch=athlon64-sse3")));
-extern void test_arch_athlon_fx (void)		__attribute__((__option__("arch=athlon-fx")));
-extern void test_arch_amdfam10 (void)		__attribute__((__option__("arch=amdfam10")));
-extern void test_arch_barcelona (void)		__attribute__((__option__("arch=barcelona")));
-extern void test_arch_foo (void)		__attribute__((__option__("arch=foo"))); /* { dg-error "bad value" } */
+extern void test_arch_i386 (void)		__attribute__((__target__("arch=i386")));
+extern void test_arch_i486 (void)		__attribute__((__target__("arch=i486")));
+extern void test_arch_i586 (void)		__attribute__((__target__("arch=i586")));
+extern void test_arch_pentium (void)		__attribute__((__target__("arch=pentium")));
+extern void test_arch_pentium_mmx (void)	__attribute__((__target__("arch=pentium-mmx")));
+extern void test_arch_winchip_c6 (void)		__attribute__((__target__("arch=winchip-c6")));
+extern void test_arch_winchip2 (void)		__attribute__((__target__("arch=winchip2")));
+extern void test_arch_c3 (void)			__attribute__((__target__("arch=c3")));
+extern void test_arch_c3_2 (void)		__attribute__((__target__("arch=c3-2")));
+extern void test_arch_i686 (void)		__attribute__((__target__("arch=i686")));
+extern void test_arch_pentiumpro (void)		__attribute__((__target__("arch=pentiumpro")));
+extern void test_arch_pentium2 (void)		__attribute__((__target__("arch=pentium2")));
+extern void test_arch_pentium3 (void)		__attribute__((__target__("arch=pentium3")));
+extern void test_arch_pentium3m (void)		__attribute__((__target__("arch=pentium3m")));
+extern void test_arch_pentium_m (void)		__attribute__((__target__("arch=pentium-m")));
+extern void test_arch_pentium4 (void)		__attribute__((__target__("arch=pentium4")));
+extern void test_arch_pentium4m (void)		__attribute__((__target__("arch=pentium4m")));
+extern void test_arch_prescott (void)		__attribute__((__target__("arch=prescott")));
+extern void test_arch_nocona (void)		__attribute__((__target__("arch=nocona")));
+extern void test_arch_core2 (void)		__attribute__((__target__("arch=core2")));
+extern void test_arch_geode (void)		__attribute__((__target__("arch=geode")));
+extern void test_arch_k6 (void)			__attribute__((__target__("arch=k6")));
+extern void test_arch_k6_2 (void)		__attribute__((__target__("arch=k6-2")));
+extern void test_arch_k6_3 (void)		__attribute__((__target__("arch=k6-3")));
+extern void test_arch_athlon (void)		__attribute__((__target__("arch=athlon")));
+extern void test_arch_athlon_tbird (void)	__attribute__((__target__("arch=athlon-tbird")));
+extern void test_arch_athlon_4 (void)		__attribute__((__target__("arch=athlon-4")));
+extern void test_arch_athlon_xp (void)		__attribute__((__target__("arch=athlon-xp")));
+extern void test_arch_athlon_mp (void)		__attribute__((__target__("arch=athlon-mp")));
+extern void test_arch_k8 (void)			__attribute__((__target__("arch=k8")));
+extern void test_arch_k8_sse3 (void)		__attribute__((__target__("arch=k8-sse3")));
+extern void test_arch_opteron (void)		__attribute__((__target__("arch=opteron")));
+extern void test_arch_opteron_sse3 (void)	__attribute__((__target__("arch=opteron-sse3")));
+extern void test_arch_athlon64 (void)		__attribute__((__target__("arch=athlon64")));
+extern void test_arch_athlon64_sse3 (void)	__attribute__((__target__("arch=athlon64-sse3")));
+extern void test_arch_athlon_fx (void)		__attribute__((__target__("arch=athlon-fx")));
+extern void test_arch_amdfam10 (void)		__attribute__((__target__("arch=amdfam10")));
+extern void test_arch_barcelona (void)		__attribute__((__target__("arch=barcelona")));
+extern void test_arch_foo (void)		__attribute__((__target__("arch=foo"))); /* { dg-error "bad value" } */
 
-extern void test_tune_i386 (void)		__attribute__((__option__("tune=i386")));
-extern void test_tune_i486 (void)		__attribute__((__option__("tune=i486")));
-extern void test_tune_i586 (void)		__attribute__((__option__("tune=i586")));
-extern void test_tune_pentium (void)		__attribute__((__option__("tune=pentium")));
-extern void test_tune_pentium_mmx (void)	__attribute__((__option__("tune=pentium-mmx")));
-extern void test_tune_winchip_c6 (void)		__attribute__((__option__("tune=winchip-c6")));
-extern void test_tune_winchip2 (void)		__attribute__((__option__("tune=winchip2")));
-extern void test_tune_c3 (void)			__attribute__((__option__("tune=c3")));
-extern void test_tune_c3_2 (void)		__attribute__((__option__("tune=c3-2")));
-extern void test_tune_i686 (void)		__attribute__((__option__("tune=i686")));
-extern void test_tune_pentiumpro (void)		__attribute__((__option__("tune=pentiumpro")));
-extern void test_tune_pentium2 (void)		__attribute__((__option__("tune=pentium2")));
-extern void test_tune_pentium3 (void)		__attribute__((__option__("tune=pentium3")));
-extern void test_tune_pentium3m (void)		__attribute__((__option__("tune=pentium3m")));
-extern void test_tune_pentium_m (void)		__attribute__((__option__("tune=pentium-m")));
-extern void test_tune_pentium4 (void)		__attribute__((__option__("tune=pentium4")));
-extern void test_tune_pentium4m (void)		__attribute__((__option__("tune=pentium4m")));
-extern void test_tune_prescott (void)		__attribute__((__option__("tune=prescott")));
-extern void test_tune_nocona (void)		__attribute__((__option__("tune=nocona")));
-extern void test_tune_core2 (void)		__attribute__((__option__("tune=core2")));
-extern void test_tune_geode (void)		__attribute__((__option__("tune=geode")));
-extern void test_tune_k6 (void)			__attribute__((__option__("tune=k6")));
-extern void test_tune_k6_2 (void)		__attribute__((__option__("tune=k6-2")));
-extern void test_tune_k6_3 (void)		__attribute__((__option__("tune=k6-3")));
-extern void test_tune_athlon (void)		__attribute__((__option__("tune=athlon")));
-extern void test_tune_athlon_tbird (void)	__attribute__((__option__("tune=athlon-tbird")));
-extern void test_tune_athlon_4 (void)		__attribute__((__option__("tune=athlon-4")));
-extern void test_tune_athlon_xp (void)		__attribute__((__option__("tune=athlon-xp")));
-extern void test_tune_athlon_mp (void)		__attribute__((__option__("tune=athlon-mp")));
-extern void test_tune_k8 (void)			__attribute__((__option__("tune=k8")));
-extern void test_tune_k8_sse3 (void)		__attribute__((__option__("tune=k8-sse3")));
-extern void test_tune_opteron (void)		__attribute__((__option__("tune=opteron")));
-extern void test_tune_opteron_sse3 (void)	__attribute__((__option__("tune=opteron-sse3")));
-extern void test_tune_athlon64 (void)		__attribute__((__option__("tune=athlon64")));
-extern void test_tune_athlon64_sse3 (void)	__attribute__((__option__("tune=athlon64-sse3")));
-extern void test_tune_athlon_fx (void)		__attribute__((__option__("tune=athlon-fx")));
-extern void test_tune_amdfam10 (void)		__attribute__((__option__("tune=amdfam10")));
-extern void test_tune_barcelona (void)		__attribute__((__option__("tune=barcelona")));
-extern void test_tune_generic (void)		__attribute__((__option__("tune=generic")));
-extern void test_tune_foo (void)		__attribute__((__option__("tune=foo"))); /* { dg-error "bad value" } */
+extern void test_tune_i386 (void)		__attribute__((__target__("tune=i386")));
+extern void test_tune_i486 (void)		__attribute__((__target__("tune=i486")));
+extern void test_tune_i586 (void)		__attribute__((__target__("tune=i586")));
+extern void test_tune_pentium (void)		__attribute__((__target__("tune=pentium")));
+extern void test_tune_pentium_mmx (void)	__attribute__((__target__("tune=pentium-mmx")));
+extern void test_tune_winchip_c6 (void)		__attribute__((__target__("tune=winchip-c6")));
+extern void test_tune_winchip2 (void)		__attribute__((__target__("tune=winchip2")));
+extern void test_tune_c3 (void)			__attribute__((__target__("tune=c3")));
+extern void test_tune_c3_2 (void)		__attribute__((__target__("tune=c3-2")));
+extern void test_tune_i686 (void)		__attribute__((__target__("tune=i686")));
+extern void test_tune_pentiumpro (void)		__attribute__((__target__("tune=pentiumpro")));
+extern void test_tune_pentium2 (void)		__attribute__((__target__("tune=pentium2")));
+extern void test_tune_pentium3 (void)		__attribute__((__target__("tune=pentium3")));
+extern void test_tune_pentium3m (void)		__attribute__((__target__("tune=pentium3m")));
+extern void test_tune_pentium_m (void)		__attribute__((__target__("tune=pentium-m")));
+extern void test_tune_pentium4 (void)		__attribute__((__target__("tune=pentium4")));
+extern void test_tune_pentium4m (void)		__attribute__((__target__("tune=pentium4m")));
+extern void test_tune_prescott (void)		__attribute__((__target__("tune=prescott")));
+extern void test_tune_nocona (void)		__attribute__((__target__("tune=nocona")));
+extern void test_tune_core2 (void)		__attribute__((__target__("tune=core2")));
+extern void test_tune_geode (void)		__attribute__((__target__("tune=geode")));
+extern void test_tune_k6 (void)			__attribute__((__target__("tune=k6")));
+extern void test_tune_k6_2 (void)		__attribute__((__target__("tune=k6-2")));
+extern void test_tune_k6_3 (void)		__attribute__((__target__("tune=k6-3")));
+extern void test_tune_athlon (void)		__attribute__((__target__("tune=athlon")));
+extern void test_tune_athlon_tbird (void)	__attribute__((__target__("tune=athlon-tbird")));
+extern void test_tune_athlon_4 (void)		__attribute__((__target__("tune=athlon-4")));
+extern void test_tune_athlon_xp (void)		__attribute__((__target__("tune=athlon-xp")));
+extern void test_tune_athlon_mp (void)		__attribute__((__target__("tune=athlon-mp")));
+extern void test_tune_k8 (void)			__attribute__((__target__("tune=k8")));
+extern void test_tune_k8_sse3 (void)		__attribute__((__target__("tune=k8-sse3")));
+extern void test_tune_opteron (void)		__attribute__((__target__("tune=opteron")));
+extern void test_tune_opteron_sse3 (void)	__attribute__((__target__("tune=opteron-sse3")));
+extern void test_tune_athlon64 (void)		__attribute__((__target__("tune=athlon64")));
+extern void test_tune_athlon64_sse3 (void)	__attribute__((__target__("tune=athlon64-sse3")));
+extern void test_tune_athlon_fx (void)		__attribute__((__target__("tune=athlon-fx")));
+extern void test_tune_amdfam10 (void)		__attribute__((__target__("tune=amdfam10")));
+extern void test_tune_barcelona (void)		__attribute__((__target__("tune=barcelona")));
+extern void test_tune_generic (void)		__attribute__((__target__("tune=generic")));
+extern void test_tune_foo (void)		__attribute__((__target__("tune=foo"))); /* { dg-error "bad value" } */
 
-extern void test_fpmath_sse (void)		__attribute__((__option__("sse2,fpmath=sse")));
-extern void test_fpmath_387 (void)		__attribute__((__option__("sse2,fpmath=387")));
-extern void test_fpmath_sse_387 (void)		__attribute__((__option__("sse2,fpmath=sse+387")));
-extern void test_fpmath_387_sse (void)		__attribute__((__option__("sse2,fpmath=387+sse")));
-extern void test_fpmath_both (void)		__attribute__((__option__("sse2,fpmath=both")));
+extern void test_fpmath_sse (void)		__attribute__((__target__("sse2,fpmath=sse")));
+extern void test_fpmath_387 (void)		__attribute__((__target__("sse2,fpmath=387")));
+extern void test_fpmath_sse_387 (void)		__attribute__((__target__("sse2,fpmath=sse+387")));
+extern void test_fpmath_387_sse (void)		__attribute__((__target__("sse2,fpmath=387+sse")));
+extern void test_fpmath_both (void)		__attribute__((__target__("sse2,fpmath=both")));
Index: gcc/testsuite/gcc.target/i386/funcspec-7.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-7.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-7.c	(working copy)
@@ -3,7 +3,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -march=k8 -mno-recip -mfpmath=sse -ffast-math" } */
 
-float do_recip  (float a) __attribute__((__option__("recip")));
+float do_recip  (float a) __attribute__((__target__("recip")));
 float do_normal (float a);
 
 float do_recip  (float a) { return 1.0f / __builtin_sqrtf (a); }
Index: gcc/testsuite/gcc.target/i386/funcspec-9.c
===================================================================
--- gcc/testsuite/gcc.target/i386/funcspec-9.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/funcspec-9.c	(working copy)
@@ -5,14 +5,14 @@
 extern void exit (int);
 
 #ifdef __SSE5__
-#warning "__SSE5__ should not be defined before #pragma GCC option."
+#warning "__SSE5__ should not be defined before #pragma GCC target."
 #endif
 
-#pragma GCC option (push)
-#pragma GCC option ("sse5,fused-madd")
+#pragma GCC push_options
+#pragma GCC target ("sse5,fused-madd")
 
 #ifndef __SSE5__
-#warning "__SSE5__ should have be defined after #pragma GCC option."
+#warning "__SSE5__ should have be defined after #pragma GCC target."
 #endif
 
 float
@@ -21,9 +21,9 @@ flt_mul_add (float a, float b, float c)
   return (a * b) + c;
 }
 
-#pragma GCC option (pop)
+#pragma GCC pop_options
 #ifdef __SSE5__
-#warning "__SSE5__ should not be defined after #pragma GCC pop option."
+#warning "__SSE5__ should not be defined after #pragma GCC pop target."
 #endif
 
 double
Index: gcc/testsuite/gcc.target/i386/sse-22.c
===================================================================
--- gcc/testsuite/gcc.target/i386/sse-22.c	(revision 139809)
+++ gcc/testsuite/gcc.target/i386/sse-22.c	(working copy)
@@ -37,7 +37,7 @@
 
 
 #ifndef DIFFERENT_PRAGMAS
-#pragma GCC option ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse5,aes,pclmul")
+#pragma GCC target ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse5,aes,pclmul")
 #endif
 
 /* Following intrinsics require immediate arguments.  They
@@ -45,19 +45,19 @@
 
 /* mmintrin.h (MMX).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("mmx")
+#pragma GCC target ("mmx")
 #endif
 #include <mmintrin.h>
 
 /* mm3dnow.h (3DNOW).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("3dnow")
+#pragma GCC target ("3dnow")
 #endif
 #include <mm3dnow.h>
 
 /* xmmintrin.h (SSE).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("sse")
+#pragma GCC target ("sse")
 #endif
 #include <xmmintrin.h>
 test_2 (_mm_shuffle_ps, __m128, __m128, __m128, 1)
@@ -71,7 +71,7 @@ test_1 (_mm_prefetch, void, void *, _MM_
 
 /* emmintrin.h (SSE2).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("sse2")
+#pragma GCC target ("sse2")
 #endif
 #include <emmintrin.h>
 test_2 (_mm_shuffle_pd, __m128d, __m128d, __m128d, 1)
@@ -85,13 +85,13 @@ test_1 (_mm_shuffle_epi32, __m128i, __m1
 
 /* pmmintrin.h (SSE3).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("sse3")
+#pragma GCC target ("sse3")
 #endif
 #include <pmmintrin.h>
 
 /* tmmintrin.h (SSSE3).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("ssse3")
+#pragma GCC target ("ssse3")
 #endif
 #include <tmmintrin.h>
 test_2 (_mm_alignr_epi8, __m128i, __m128i, __m128i, 1)
@@ -99,7 +99,7 @@ test_2 (_mm_alignr_pi8, __m64, __m64, __
 
 /* ammintrin.h (SSE4A).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("sse4a")
+#pragma GCC target ("sse4a")
 #endif
 #include <ammintrin.h>
 test_1x (_mm_extracti_si64, __m128i, __m128i, 1, 1)
@@ -110,7 +110,7 @@ test_2x (_mm_inserti_si64, __m128i, __m1
 /* Note, nmmintrin.h includes smmintrin.h, and smmintrin.h checks for the
    #ifdef.  So just set the option to SSE4.2.  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("sse4.2")
+#pragma GCC target ("sse4.2")
 #endif
 #include <nmmintrin.h>
 test_2 (_mm_blend_epi16, __m128i, __m128i, __m128i, 1)
@@ -148,7 +148,7 @@ test_4 (_mm_cmpestrz, int, __m128i, int,
 
 /* bmmintrin.h (SSE5).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("sse5")
+#pragma GCC target ("sse5")
 #endif
 #include <bmmintrin.h>
 test_1 (_mm_roti_epi8, __m128i, __m128i, 1)
@@ -158,7 +158,7 @@ test_1 (_mm_roti_epi64, __m128i, __m128i
 
 /* wmmintrin.h (AES/PCLMUL).  */
 #ifdef DIFFERENT_PRAGMAS
-#pragma GCC option ("aes,pclmul")
+#pragma GCC target ("aes,pclmul")
 #endif
 #include <wmmintrin.h>
 test_1 (_mm_aeskeygenassist_si128, __m128i, __m128i, 1)
Index: gcc/testsuite/gcc.dg/pr36997.c
===================================================================
--- gcc/testsuite/gcc.dg/pr36997.c	(revision 139809)
+++ gcc/testsuite/gcc.dg/pr36997.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile { target x86_64-*-* i?86-*-* } } */
-/* { dg-options "-std=c99" } */
+/* { dg-options "-std=c99 -msse2" } */
 
 typedef int __m64 __attribute__ ((__vector_size__ (8), __may_alias__));
 __m64 _mm_add_si64 (__m64 __m1, __m64 __m2)
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 139809)
+++ gcc/cp/decl.c	(working copy)
@@ -66,7 +66,7 @@ static tree grok_reference_init (tree, t
 static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
 			 int, int, tree);
 static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (tree, tree);
+static tree builtin_function_1 (tree, tree, bool);
 static tree build_library_fn_1 (tree, enum tree_code, tree);
 static int member_function_or_else (tree, tree, enum overload_flags);
 static void bad_specifiers (tree, const char *, int, int, int, int,
@@ -1764,6 +1764,20 @@ duplicate_decls (tree newdecl, tree oldd
       if (TREE_DEPRECATED (newdecl))
 	TREE_DEPRECATED (olddecl) = 1;
 
+      /* Preserve function specific target and optimization options */
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+	{
+	  if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl)
+	      && !DECL_FUNCTION_SPECIFIC_TARGET (newdecl))
+	    DECL_FUNCTION_SPECIFIC_TARGET (newdecl)
+	      = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
+
+	  if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl)
+	      && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
+	    DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
+	      = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
+	}
+
       /* Merge the initialization information.  */
       if (DECL_INITIAL (newdecl) == NULL_TREE
 	  && DECL_INITIAL (olddecl) != NULL_TREE)
@@ -3497,7 +3511,7 @@ cp_make_fname_decl (tree id, int type_de
 }
 
 static tree
-builtin_function_1 (tree decl, tree context)
+builtin_function_1 (tree decl, tree context, bool is_global)
 {
   tree          id = DECL_NAME (decl);
   const char *name = IDENTIFIER_POINTER (id);
@@ -3518,7 +3532,10 @@ builtin_function_1 (tree decl, tree cont
 
   DECL_CONTEXT (decl) = context;
 
-  pushdecl (decl);
+  if (is_global)
+    pushdecl_top_level (decl);
+  else
+    pushdecl (decl);
 
   /* A function in the user's namespace should have an explicit
      declaration before it is used.  Mark the built-in function as
@@ -3551,11 +3568,36 @@ cxx_builtin_function (tree decl)
     {
       tree decl2 = copy_node(decl);
       push_namespace (std_identifier);
-      builtin_function_1 (decl2, std_node);
+      builtin_function_1 (decl2, std_node, false);
+      pop_namespace ();
+    }
+
+  return builtin_function_1 (decl, NULL_TREE, false);
+}
+
+/* Like cxx_builtin_function, but guarantee the function is added to the global
+   scope.  This is to allow function specific options to add new machine
+   dependent builtins when the target ISA changes via attribute((target(...)))
+   which saves space on program startup if the program does not use non-generic
+   ISAs.  */
+
+tree
+cxx_builtin_function_ext_scope (tree decl)
+{
+
+  tree          id = DECL_NAME (decl);
+  const char *name = IDENTIFIER_POINTER (id);
+  /* All builtins that don't begin with an '_' should additionally
+     go in the 'std' namespace.  */
+  if (name[0] != '_')
+    {
+      tree decl2 = copy_node(decl);
+      push_namespace (std_identifier);
+      builtin_function_1 (decl2, std_node, true);
       pop_namespace ();
     }
 
-  return builtin_function_1 (decl, NULL_TREE);
+  return builtin_function_1 (decl, NULL_TREE, true);
 }
 
 /* Generate a FUNCTION_DECL with the typical flags for a runtime library
Index: gcc/cp/cp-objcp-common.h
===================================================================
--- gcc/cp/cp-objcp-common.h	(revision 139809)
+++ gcc/cp/cp-objcp-common.h	(working copy)
@@ -86,6 +86,8 @@ extern tree objcp_tsubst_copy_and_build 
 #define LANG_HOOKS_COMDAT_GROUP cxx_comdat_group
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function
+#undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
+#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE cxx_builtin_function_ext_scope
 #undef	LANG_HOOKS_TYPE_HASH_EQ
 #define LANG_HOOKS_TYPE_HASH_EQ	cxx_type_hash_eq
 #undef LANG_HOOKS_MISSING_NORETURN_OK_P
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 139809)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4364,6 +4364,7 @@ extern tree register_dtor_fn			(tree);
 extern tmpl_spec_kind current_tmpl_spec_kind	(int);
 extern tree cp_fname_init			(const char *, tree *);
 extern tree cxx_builtin_function		(tree decl);
+extern tree cxx_builtin_function_ext_scope	(tree decl);
 extern tree check_elaborated_type_specifier	(enum tag_types, tree, bool);
 extern void warn_extern_redeclared_static	(tree, tree);
 extern const char *cxx_comdat_group		(tree);
Index: gcc/c-objc-common.h
===================================================================
--- gcc/c-objc-common.h	(revision 139809)
+++ gcc/c-objc-common.h	(working copy)
@@ -69,6 +69,8 @@ extern void c_initialize_diagnostics (di
 #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL c_dup_lang_specific_decl
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function
+#undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
+#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE c_builtin_function_ext_scope
 
 /* Attribute hooks.  */
 #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h	(revision 139809)
+++ gcc/c-tree.h	(working copy)
@@ -488,6 +488,7 @@ extern void push_parm_decl (const struct
 extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
 							struct c_declarator *);
 extern tree c_builtin_function (tree);
+extern tree c_builtin_function_ext_scope (tree);
 extern void shadow_tag (const struct c_declspecs *);
 extern void shadow_tag_warned (const struct c_declspecs *, int);
 extern tree start_enum (struct c_enum_contents *, tree);
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 139809)
+++ gcc/opts.h	(working copy)
@@ -65,13 +65,14 @@ extern const unsigned int cl_options_cou
 extern const char *const lang_names[];
 extern const unsigned int cl_lang_count;
 
+#define CL_SAVE			(1 << 17) /* Target-specific option for attribute.  */
 #define CL_PARAMS               (1 << 18) /* Fake entry.  Used to display --param info with --help.  */
 #define CL_WARNING		(1 << 19) /* Enables an (optional) warning message.  */
 #define CL_OPTIMIZATION		(1 << 20) /* Enables an (optional) optimization.  */
 #define CL_TARGET		(1 << 21) /* Target-specific option.  */
 #define CL_COMMON		(1 << 22) /* Language-independent.  */
 
-#define CL_MIN_OPTION_CLASS	CL_PARAMS
+#define CL_MIN_OPTION_CLASS	CL_SAVE
 #define CL_MAX_OPTION_CLASS	CL_COMMON
 
 /* From here on the bits describe attributes of the options.
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 139809)
+++ gcc/c-decl.c	(working copy)
@@ -2843,6 +2843,31 @@ c_builtin_function (tree decl)
 
   return decl;
 }
+
+tree
+c_builtin_function_ext_scope (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  tree   id = DECL_NAME (decl);
+
+  const char *name = IDENTIFIER_POINTER (id);
+  C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
+
+  /* Should never be called on a symbol with a preexisting meaning.  */
+  gcc_assert (!I_SYMBOL_BINDING (id));
+
+  bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false);
+
+  /* Builtins in the implementation namespace are made visible without
+     needing to be explicitly declared.  See push_file_scope.  */
+  if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+    {
+      TREE_CHAIN (decl) = visible_builtins;
+      visible_builtins = decl;
+    }
+
+  return decl;
+}
 
 /* Called when a declaration is seen that contains no names to declare.
    If its type is a reference to a structure, union or enum inherited
Index: gcc/langhooks.c
===================================================================
--- gcc/langhooks.c	(revision 139809)
+++ gcc/langhooks.c	(working copy)
@@ -540,13 +540,16 @@ lhd_omp_firstprivatize_type_sizes (struc
 {
 }
 
-tree
-add_builtin_function (const char *name,
-		      tree type,
-		      int function_code,
-		      enum built_in_class cl,
-		      const char *library_name,
-		      tree attrs)
+/* Common function for add_builtin_function and
+   add_builtin_function_ext_scope.  */
+static tree
+add_builtin_function_common (const char *name,
+			     tree type,
+			     int function_code,
+			     enum built_in_class cl,
+			     const char *library_name,
+			     tree attrs,
+			     tree (*hook) (tree))
 {
   tree   id = get_identifier (name);
   tree decl = build_decl (FUNCTION_DECL, id, type);
@@ -571,8 +574,43 @@ add_builtin_function (const char *name,
   else
     decl_attributes (&decl, NULL_TREE, 0);
 
-  return lang_hooks.builtin_function (decl);
+  return hook (decl);
+
+}
+
+/* Create a builtin function.  */
 
+tree
+add_builtin_function (const char *name,
+		      tree type,
+		      int function_code,
+		      enum built_in_class cl,
+		      const char *library_name,
+		      tree attrs)
+{
+  return add_builtin_function_common (name, type, function_code, cl,
+				      library_name, attrs,
+				      lang_hooks.builtin_function);
+}
+
+/* Like add_builtin_function, but make sure the scope is the external scope.
+   This is used to delay putting in back end builtin functions until the ISA
+   that defines the builtin is declared via function specific target options,
+   which can save memory for machines like the x86_64 that have multiple ISAs.
+   If this points to the same function as builtin_function, the backend must
+   add all of the builtins at program initialization time.  */
+
+tree
+add_builtin_function_ext_scope (const char *name,
+				tree type,
+				int function_code,
+				enum built_in_class cl,
+				const char *library_name,
+				tree attrs)
+{
+  return add_builtin_function_common (name, type, function_code, cl,
+				      library_name, attrs,
+				      lang_hooks.builtin_function_ext_scope);
 }
 
 tree
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	(revision 139809)
+++ gcc/langhooks.h	(working copy)
@@ -410,6 +410,14 @@ struct lang_hooks
   /* Do language specific processing in the builtin function DECL  */
   tree (*builtin_function) (tree decl);
 
+  /* Like builtin_function, but make sure the scope is the external scope.
+     This is used to delay putting in back end builtin functions until the ISA
+     that defines the builtin is declared via function specific target options,
+     which can save memory for machines like the x86_64 that have multiple
+     ISAs.  If this points to the same function as builtin_function, the
+     backend must add all of the builtins at program initialization time.  */
+  tree (*builtin_function_ext_scope) (tree decl);
+
   /* Used to set up the tree_contains_structure array for a frontend. */
   void (*init_ts) (void);
 
@@ -429,4 +437,10 @@ extern tree add_builtin_function (const 
 				  const char *library_name,
 				  tree attrs);
 
+extern tree add_builtin_function_ext_scope (const char *name, tree type,
+					    int function_code,
+					    enum built_in_class cl,
+					    const char *library_name,
+					    tree attrs);
+
 #endif /* GCC_LANG_HOOKS_H */
Index: gcc/c-pragma.c
===================================================================
--- gcc/c-pragma.c	(revision 139809)
+++ gcc/c-pragma.c	(working copy)
@@ -866,15 +866,11 @@ handle_pragma_diagnostic(cpp_reader *ARG
   GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
 }
 
-/* Stack of the #pragma GCC options created with #pragma GCC option push.  */
-static GTY(()) VEC(tree,gc) *option_stack;
-
-/*  Parse #pragma GCC option (xxx) to set target specific options.  */
+/*  Parse #pragma GCC target (xxx) to set target specific options.  */
 static void
-handle_pragma_option(cpp_reader *ARG_UNUSED(dummy))
+handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
 {
   enum cpp_ttype token;
-  const char *name;
   tree x;
   bool close_paren_needed_p = false;
 
@@ -884,12 +880,6 @@ handle_pragma_option(cpp_reader *ARG_UNU
       return;
     }
 
-  if (!targetm.target_option.pragma_parse)
-    {
-      error ("#pragma GCC option is not supported for this system");
-      return;
-    }
-
   token = pragma_lex (&x);
   if (token == CPP_OPEN_PAREN)
     {
@@ -897,76 +887,9 @@ handle_pragma_option(cpp_reader *ARG_UNU
       token = pragma_lex (&x);
     }
 
-  if (token == CPP_NAME)
+  if (token != CPP_STRING)
     {
-      bool call_pragma_parse_p = false;
-      bool ok_p;
-
-      name = IDENTIFIER_POINTER (x);
-      if (strcmp (name, "reset") == 0)
-	{
-	  current_option_pragma = NULL_TREE;
-	  call_pragma_parse_p = true;
-	}
-
-      else if (strcmp (name, "push") == 0)
-	VEC_safe_push (tree, gc, option_stack,
-		       copy_list (current_option_pragma));
-
-      else if (strcmp (name, "pop") == 0)
-	{
-	  int len = VEC_length (tree, option_stack);
-	  if (len == 0)
-	    {
-	      GCC_BAD ("%<#pragma GCC option pop%> without a %<#pragma GCC "
-		       "option push%>");
-	      return;
-	    }
-	  else
-	    {
-	      VEC_truncate (tree, option_stack, len-1);
-	      current_option_pragma = ((len > 1)
-				       ? VEC_last (tree, option_stack)
-				       : NULL_TREE);
-
-	      call_pragma_parse_p = true;
-	    }
-	}
-
-      else
-	{
-	  GCC_BAD ("%<#pragma GCC option%> is not a string or "
-		   "push/pop/reset");
-	  return;
-	}
-
-      token = pragma_lex (&x);
-      if (close_paren_needed_p)
-	{
-	  if (token == CPP_CLOSE_PAREN)
-	    token = pragma_lex (&x);
-	  else
-	    GCC_BAD ("%<#pragma GCC option ([push|pop|reset])%> does not "
-		     "have a final %<)%>.");
-	}
-
-      if (token != CPP_EOF)
-	{
-	  GCC_BAD ("%<#pragma GCC option [push|pop|reset]%> is badly "
-		   "formed");
-	  return;
-	}
-
-      /* See if we need to call the pragma_parse hook.  This must occur at the
-	 end after processing all of the tokens, or we may get spurious errors
-	 when we define or undef macros.  */
-      ok_p = targetm.target_option.pragma_parse (current_option_pragma);
-      gcc_assert (ok_p);
-    }
-
-  else if (token != CPP_STRING)
-    {
-      GCC_BAD ("%<#pragma GCC option%> is not a string or push/pop/reset");
+      GCC_BAD ("%<#pragma GCC option%> is not a string");
       return;
     }
 
@@ -993,34 +916,29 @@ handle_pragma_option(cpp_reader *ARG_UNU
 	  if (token == CPP_CLOSE_PAREN)
 	    token = pragma_lex (&x);
 	  else
-	    GCC_BAD ("%<#pragma GCC option (string [,string]...)%> does "
+	    GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
 		     "not have a final %<)%>.");
 	}
 
       if (token != CPP_EOF)
 	{
-	  error ("#pragma GCC option string... is badly formed");
+	  error ("#pragma GCC target string... is badly formed");
 	  return;
 	}
 
       /* put arguments in the order the user typed them.  */
       args = nreverse (args);
 
-      if (targetm.target_option.pragma_parse (args))
-	current_option_pragma = args;
+      if (targetm.target_option.pragma_parse (args, NULL_TREE))
+	current_target_pragma = args;
     }
 }
 
-/* Stack of the #pragma GCC optimize options created with #pragma GCC optimize
-   push.  */
-static GTY(()) VEC(tree,gc) *optimize_stack;
-
 /* Handle #pragma GCC optimize to set optimization options.  */
 static void
-handle_pragma_optimize(cpp_reader *ARG_UNUSED(dummy))
+handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
 {
   enum cpp_ttype token;
-  const char *name;
   tree x;
   bool close_paren_needed_p = false;
   tree optimization_previous_node = optimization_current_node;
@@ -1038,95 +956,9 @@ handle_pragma_optimize(cpp_reader *ARG_U
       token = pragma_lex (&x);
     }
 
-  if (token == CPP_NAME)
-    {
-      bool call_opt_p = false;
-
-      name = IDENTIFIER_POINTER (x);
-      if (strcmp (name, "reset") == 0)
-	{
-	  struct cl_optimization *def
-	    = TREE_OPTIMIZATION (optimization_default_node);
-	  current_optimize_pragma = NULL_TREE;
-	  optimization_current_node = optimization_default_node;
-	  cl_optimization_restore (def);
-	  call_opt_p = true;
-	}
-
-      else if (strcmp (name, "push") == 0)
-	VEC_safe_push (tree, gc, optimize_stack, current_optimize_pragma);
-
-      else if (strcmp (name, "pop") == 0)
-	{
-	  int len = VEC_length (tree, optimize_stack);
-	  if (len == 0)
-	    {
-	      GCC_BAD ("%<#pragma GCC optimize pop%> without a %<#pragma "
-		       "GCC optimize push%>");
-	      return;
-	    }
-	  else
-	    {
-	      VEC_truncate (tree, optimize_stack, len-1);
-	      current_optimize_pragma
-		= ((len > 1)
-		   ? VEC_last (tree, optimize_stack)
-		   : NULL_TREE);
-
-	      call_opt_p = true;
-	      if (current_optimize_pragma)
-		{
-		  bool ok_p
-		    = parse_optimize_options (current_optimize_pragma, false);
-		  gcc_assert (ok_p);	/* should be parsed previously.  */
-		  optimization_current_node = build_optimization_node ();
-		}
-	      else
-		{
-		  struct cl_optimization *opt
-		    = TREE_OPTIMIZATION (optimization_default_node);
-		  optimization_current_node = optimization_default_node;
-		  cl_optimization_restore (opt);
-		}
-	    }
-	}
-
-      else
-	{
-	  GCC_BAD ("%<#pragma GCC optimize%> is not a string or "
-		   "push/pop/reset");
-	  return;
-	}
-
-      token = pragma_lex (&x);
-      if (close_paren_needed_p)
-	{
-	  if (token == CPP_CLOSE_PAREN)
-	    token = pragma_lex (&x);
-	  else
-	    GCC_BAD ("%<#pragma GCC optimize ([push|pop|reset])%> does not "
-		     "have a final %<)%>.");
-	}
-
-      if (token != CPP_EOF)
-	{
-	  GCC_BAD ("%<#pragma GCC optimize [push|pop|reset]%> is badly "
-		   "formed");
-	  return;
-	}
-
-      if (call_opt_p &&
-	  (optimization_previous_node != optimization_current_node))
-	c_cpp_builtins_optimize_pragma (parse_in,
-					optimization_previous_node,
-					optimization_current_node);
-
-    }
-
-  else if (token != CPP_STRING && token != CPP_NUMBER)
+  if (token != CPP_STRING && token != CPP_NUMBER)
     {
-      GCC_BAD ("%<#pragma GCC optimize%> is not a string, number, or "
-	       "push/pop/reset");
+      GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
       return;
     }
 
@@ -1166,6 +998,7 @@ handle_pragma_optimize(cpp_reader *ARG_U
       args = nreverse (args);
 
       parse_optimize_options (args, false);
+      current_optimize_pragma = chainon (current_optimize_pragma, args);
       optimization_current_node = build_optimization_node ();
       c_cpp_builtins_optimize_pragma (parse_in,
 				      optimization_previous_node,
@@ -1173,6 +1006,133 @@ handle_pragma_optimize(cpp_reader *ARG_U
     }
 }
 
+/* Stack of the #pragma GCC options created with #pragma GCC push_option.  Save
+   both the binary representation of the options and the TREE_LIST of
+   strings that will be added to the function's attribute list.  */
+typedef struct opt_stack GTY(())
+{
+  struct opt_stack *prev;
+  tree target_binary;
+  tree target_strings;
+  tree optimize_binary;
+  tree optimize_strings;
+} opt_stack;
+
+static GTY(()) struct opt_stack * options_stack;
+
+/* Handle #pragma GCC push_options to save the current target and optimization
+   options.  */
+
+static void
+handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x = 0;
+  opt_stack *p;
+
+  token = pragma_lex (&x);
+  if (token != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma push_options%>");
+      return;
+    }
+
+  p = GGC_NEW (opt_stack);
+  p->prev = options_stack;
+  options_stack = p;
+
+  /* Save optimization and target flags in binary format.  */
+  p->optimize_binary = build_optimization_node ();
+  p->target_binary = build_target_option_node ();
+
+  /* Save optimization and target flags in string list format.  */
+  p->optimize_strings = copy_list (current_optimize_pragma);
+  p->target_strings = copy_list (current_target_pragma);
+}
+
+/* Handle #pragma GCC pop_options to restore the current target and
+   optimization options from a previous push_options.  */
+
+static void
+handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x = 0;
+  opt_stack *p;
+
+  token = pragma_lex (&x);
+  if (token != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma pop_options%>");
+      return;
+    }
+
+  if (! options_stack)
+    {
+      warning (OPT_Wpragmas,
+	       "%<#pragma GCC pop_options%> without a corresponding "
+	       "%<#pragma GCC push_options%>");
+      return;
+    }
+
+  p = options_stack;
+  options_stack = p->prev;
+
+  if (p->target_binary != target_option_current_node)
+    {
+      (void) targetm.target_option.pragma_parse (NULL_TREE, p->target_binary);
+      target_option_current_node = p->target_binary;
+    }
+
+  if (p->optimize_binary != optimization_current_node)
+    {
+      tree old_optimize = optimization_current_node;
+      cl_optimization_restore (TREE_OPTIMIZATION (p->optimize_binary));
+      c_cpp_builtins_optimize_pragma (parse_in, old_optimize,
+				      p->optimize_binary);
+      optimization_current_node = p->optimize_binary;
+    }
+
+  current_target_pragma = p->target_strings;
+  current_optimize_pragma = p->optimize_strings;
+}
+
+/* Handle #pragma GCC reset_options to restore the current target and
+   optimization options to the original options used on the command line.  */
+
+static void
+handle_pragma_reset_options (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x = 0;
+  tree new_optimize = optimization_default_node;
+  tree new_target = target_option_default_node;
+
+  token = pragma_lex (&x);
+  if (token != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma reset_options%>");
+      return;
+    }
+
+  if (new_target != target_option_current_node)
+    {
+      (void) targetm.target_option.pragma_parse (NULL_TREE, new_target);
+      target_option_current_node = new_target;
+    }
+
+  if (new_optimize != optimization_current_node)
+    {
+      tree old_optimize = optimization_current_node;
+      cl_optimization_restore (TREE_OPTIMIZATION (new_optimize));
+      c_cpp_builtins_optimize_pragma (parse_in, old_optimize, new_optimize);
+      optimization_current_node = new_optimize;
+    }
+
+  current_target_pragma = NULL_TREE;
+  current_optimize_pragma = NULL_TREE;
+}
+
 /* Print a plain user-specified message.  */
 
 static void
@@ -1368,8 +1328,11 @@ init_pragma (void)
 #endif
 
   c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
-  c_register_pragma ("GCC", "option", handle_pragma_option);
+  c_register_pragma ("GCC", "target", handle_pragma_target);
   c_register_pragma ("GCC", "optimize", handle_pragma_optimize);
+  c_register_pragma ("GCC", "push_options", handle_pragma_push_options);
+  c_register_pragma ("GCC", "pop_options", handle_pragma_pop_options);
+  c_register_pragma ("GCC", "reset_options", handle_pragma_reset_options);
 
   c_register_pragma_with_expansion (0, "redefine_extname", handle_pragma_redefine_extname);
   c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h	(revision 139809)
+++ gcc/target-def.h	(working copy)
@@ -766,7 +766,8 @@
 
 /* Function specific option attribute support.  */
 #ifndef TARGET_OPTION_VALID_ATTRIBUTE_P
-#define TARGET_OPTION_VALID_ATTRIBUTE_P NULL
+#define TARGET_OPTION_VALID_ATTRIBUTE_P \
+  default_target_option_valid_attribute_p
 #endif
 
 #ifndef TARGET_OPTION_SAVE
@@ -782,21 +783,13 @@
 #endif
 
 #ifndef TARGET_OPTION_PRAGMA_PARSE
-#define TARGET_OPTION_PRAGMA_PARSE NULL
+#define TARGET_OPTION_PRAGMA_PARSE default_target_option_pragma_parse
 #endif
 
 #ifndef TARGET_OPTION_CAN_INLINE_P
 #define TARGET_OPTION_CAN_INLINE_P default_target_option_can_inline_p
 #endif
 
-#ifndef TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION
-#define TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION false
-#endif
-
-#ifndef TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION
-#define TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION false
-#endif
-
 #define TARGET_OPTION_HOOKS			\
   {						\
     TARGET_OPTION_VALID_ATTRIBUTE_P,		\
@@ -805,8 +798,6 @@
     TARGET_OPTION_PRINT,			\
     TARGET_OPTION_PRAGMA_PARSE,			\
     TARGET_OPTION_CAN_INLINE_P,			\
-    TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION, \
-    TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION, \
   }
 
 /* The whole shebang.  */
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c	(revision 139809)
+++ gcc/tree-inline.c	(working copy)
@@ -4369,6 +4369,11 @@ build_duplicate_type (tree type)
 bool
 tree_can_inline_p (tree caller, tree callee)
 {
+#if 0
+  /* This causes a regression in SPEC in that it prevents a cold function from
+     inlining a hot function.  Perhaps this should only apply to functions
+     that the user declares hot/cold/optimize explicitly.  */
+
   /* Don't inline a function with a higher optimization level than the
      caller, or with different space constraints (hot/cold functions).  */
   tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (caller);
@@ -4390,6 +4395,7 @@ tree_can_inline_p (tree caller, tree cal
 	  || (caller_opt->optimize_size != callee_opt->optimize_size))
 	return false;
     }
+#endif
 
   /* Allow the backend to decide if inlining is ok.  */
   return targetm.target_option.can_inline_p (caller, callee);
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 139809)
+++ gcc/c-common.c	(working copy)
@@ -571,7 +571,7 @@ static tree handle_warn_unused_result_at
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
-static tree handle_option_attribute (tree *, tree, tree, int, bool *);
+static tree handle_target_attribute (tree *, tree, tree, int, bool *);
 static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
 
 static void check_function_nonnull (tree, int, tree *);
@@ -856,8 +856,8 @@ const struct attribute_spec c_common_att
 			      handle_error_attribute },
   { "error",		      1, 1, true,  false, false,
 			      handle_error_attribute },
-  { "option",                 1, -1, true, false, false,
-			      handle_option_attribute },
+  { "target",                 1, -1, true, false, false,
+			      handle_target_attribute },
   { "optimize",               1, -1, true, false, false,
 			      handle_optimize_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
@@ -5260,34 +5260,8 @@ handle_hot_attribute (tree *node, tree n
 		   name, "cold");
 	  *no_add_attrs = true;
 	}
-      else
-	{
-	  tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
-
-	  /* If we are not at -O3, but are optimizing, turn on -O3
-	     optimizations just for this one function.  */
-	  if (((optimize > 0 && optimize < 3) || optimize_size)
-	      && targetm.target_option.hot_attribute_sets_optimization
-	      && (!old_opts || old_opts == optimization_default_node))
-	    {
-	      /* Create the hot optimization node if needed.  */
-	      if (!optimization_hot_node)
-		{
-		  struct cl_optimization current_options;
-		  static const char *os_argv[] = { NULL, "-O3", NULL };
-
-		  cl_optimization_save (&current_options);
-		  decode_options (2, os_argv);
-		  optimization_hot_node = build_optimization_node ();
-		  cl_optimization_restore (&current_options);
-		}
-
-	      DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
-		= optimization_hot_node;
-	    }
-	  /* Most of the rest of the hot processing is done later with
-	     lookup_attribute.  */
-	}
+      /* Most of the rest of the hot processing is done later with
+	 lookup_attribute.  */
     }
   else
     {
@@ -5312,34 +5286,8 @@ handle_cold_attribute (tree *node, tree 
 		   name, "hot");
 	  *no_add_attrs = true;
 	}
-      else
-	{
-	  tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
-
-	  /* If we are optimizing, but not optimizing for space, turn on -Os
-	     optimizations just for this one function.  */
-	  if (optimize && !optimize_size
-	      && targetm.target_option.cold_attribute_sets_optimization
-	      && (!old_opts || old_opts == optimization_default_node))
-	    {
-	      /* Create the cold optimization node if needed.  */
-	      if (!optimization_cold_node)
-		{
-		  struct cl_optimization current_options;
-		  static const char *os_argv[] = { NULL, "-Os", NULL };
-
-		  cl_optimization_save (&current_options);
-		  decode_options (2, os_argv);
-		  optimization_cold_node = build_optimization_node ();
-		  cl_optimization_restore (&current_options);
-		}
-
-	      DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
-		= optimization_cold_node;
-	    }
-	  /* Most of the rest of the cold processing is done later with
-	     lookup_attribute.  */
-	}
+      /* Most of the rest of the cold processing is done later with
+	 lookup_attribute.  */
     }
   else
     {
@@ -7038,11 +6986,10 @@ handle_type_generic_attribute (tree *nod
   return NULL_TREE;
 }
 
-/* For handling "option" attribute. arguments as in
-   struct attribute_spec.handler.  */
+/* Handle a "target" attribute.  */
 
 static tree
-handle_option_attribute (tree *node, tree name, tree args, int flags,
+handle_target_attribute (tree *node, tree name, tree args, int flags,
 			 bool *no_add_attrs)
 {
   /* Ensure we have a function type.  */
@@ -7051,14 +6998,6 @@ handle_option_attribute (tree *node, tre
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
-  else if (targetm.target_option.valid_attribute_p
-	   == default_target_option_valid_attribute_p)
-    {
-      warning (OPT_Wattributes,
-	       "%qE attribute is not supported on this machine",
-	       name);
-      *no_add_attrs = true;
-    }
   else if (! targetm.target_option.valid_attribute_p (*node, name, args,
 						      flags))
     *no_add_attrs = true;
Index: gcc/opt-functions.awk
===================================================================
--- gcc/opt-functions.awk	(revision 139809)
+++ gcc/opt-functions.awk	(working copy)
@@ -71,6 +71,7 @@ function switch_flags (flags)
 	result = result \
 	  test_flag("Common", flags, " | CL_COMMON") \
 	  test_flag("Target", flags, " | CL_TARGET") \
+	  test_flag("Save", flags, " | CL_SAVE") \
 	  test_flag("Joined", flags, " | CL_JOINED") \
 	  test_flag("JoinedOrMissing", flags, " | CL_JOINED | CL_MISSING_OK") \
 	  test_flag("Separate", flags, " | CL_SEPARATE") \
Index: gcc/config/i386/i386-c.c
===================================================================
--- gcc/config/i386/i386-c.c	(revision 139809)
+++ gcc/config/i386/i386-c.c	(working copy)
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  
 #include "cpplib.h"
 #include "c-pragma.h"
 
-static bool ix86_pragma_option_parse (tree);
+static bool ix86_pragma_target_parse (tree, tree);
 static void ix86_target_macros_internal
   (int, enum processor_type, enum processor_type, enum fpmath_unit,
    void (*def_or_undef) (cpp_reader *, const char *));
@@ -232,11 +232,12 @@ ix86_target_macros_internal (int isa_fla
 }
 
 
-/* Hook to validate the current #pragma option and set the state, and update
-   the macros based on what was changed.  */
+/* 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.  */
 
 static bool
-ix86_pragma_option_parse (tree args)
+ix86_pragma_target_parse (tree args, tree pop_target)
 {
   tree prev_tree = build_target_option_node ();
   tree cur_tree;
@@ -252,12 +253,14 @@ ix86_pragma_option_parse (tree args)
 
   if (! args)
     {
-      cur_tree = target_option_default_node;
+      cur_tree = ((pop_target)
+		  ? pop_target
+		  : target_option_default_node);
       cl_target_option_restore (TREE_TARGET_OPTION (cur_tree));
     }
   else
     {
-      cur_tree = ix86_valid_option_attribute_tree (args);
+      cur_tree = ix86_valid_target_attribute_tree (args);
       if (!cur_tree)
 	return false;
     }
@@ -339,8 +342,8 @@ ix86_target_macros (void)
 void
 ix86_register_pragmas (void)
 {
-  /* Update pragma hook to allow parsing #pragma GCC option.  */
-  targetm.target_option.pragma_parse = ix86_pragma_option_parse;
+  /* Update pragma hook to allow parsing #pragma GCC target.  */
+  targetm.target_option.pragma_parse = ix86_pragma_target_parse;
 
 #ifdef REGISTER_SUBTARGET_PRAGMAS
   REGISTER_SUBTARGET_PRAGMAS ();
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h	(revision 139809)
+++ gcc/config/i386/i386-protos.h	(working copy)
@@ -204,7 +204,7 @@ extern int ix86_constant_alignment (tree
 extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
 extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
 extern int x86_field_alignment (tree, int);
-extern tree ix86_valid_option_attribute_tree (tree);
+extern tree ix86_valid_target_attribute_tree (tree);
 #endif
 
 extern rtx ix86_tls_get_addr (void);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 139809)
+++ gcc/config/i386/i386.c	(working copy)
@@ -1793,6 +1793,7 @@ static int ix86_function_regparm (const_
 static void ix86_compute_frame_layout (struct ix86_frame *);
 static bool ix86_expand_vector_init_one_nonzero (bool, enum machine_mode,
 						 rtx, rtx, int);
+static void ix86_add_new_builtins (int);
 
 enum ix86_function_specific_strings
 {
@@ -1809,8 +1810,8 @@ static void ix86_function_specific_save 
 static void ix86_function_specific_restore (struct cl_target_option *);
 static void ix86_function_specific_print (FILE *, int,
 					  struct cl_target_option *);
-static bool ix86_valid_option_attribute_p (tree, tree, tree, int);
-static bool ix86_valid_option_attribute_inner_p (tree, char *[]);
+static bool ix86_valid_target_attribute_p (tree, tree, tree, int);
+static bool ix86_valid_target_attribute_inner_p (tree, char *[]);
 static bool ix86_can_inline_p (tree, tree);
 static void ix86_set_current_function (tree);
 
@@ -2583,7 +2584,7 @@ override_options (bool main_args_p)
   int const pta_size = ARRAY_SIZE (processor_alias_table);
 
   /* Set up prefix/suffix so the error messages refer to either the command
-     line argument, or the attribute(option).  */
+     line argument, or the attribute(target).  */
   if (main_args_p)
     {
       prefix = "-m";
@@ -3366,12 +3367,12 @@ ix86_function_specific_print (FILE *file
 }
 
 
-/* Inner function to process the attribute((option(...))), take an argument and
+/* Inner function to process the attribute((target(...))), take an argument and
    set the current options from the argument. If we have a list, recursively go
    over the list.  */
 
 static bool
-ix86_valid_option_attribute_inner_p (tree args, char *p_strings[])
+ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
 {
   char *next_optstr;
   bool ret = true;
@@ -3462,7 +3463,7 @@ ix86_valid_option_attribute_inner_p (tre
 
       for (; args; args = TREE_CHAIN (args))
 	if (TREE_VALUE (args)
-	    && !ix86_valid_option_attribute_inner_p (TREE_VALUE (args), p_strings))
+	    && !ix86_valid_target_attribute_inner_p (TREE_VALUE (args), p_strings))
 	  ret = false;
 
       return ret;
@@ -3531,7 +3532,7 @@ ix86_valid_option_attribute_inner_p (tre
       /* Process the option.  */
       if (opt == N_OPTS)
 	{
-	  error ("attribute(option(\"%s\")) is unknown", orig_p);
+	  error ("attribute(target(\"%s\")) is unknown", orig_p);
 	  ret = false;
 	}
 
@@ -3570,7 +3571,7 @@ ix86_valid_option_attribute_inner_p (tre
 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL.  */
 
 tree
-ix86_valid_option_attribute_tree (tree args)
+ix86_valid_target_attribute_tree (tree args)
 {
   const char *orig_arch_string = ix86_arch_string;
   const char *orig_tune_string = ix86_tune_string;
@@ -3584,7 +3585,7 @@ ix86_valid_option_attribute_tree (tree a
     = TREE_TARGET_OPTION (target_option_default_node);
 
   /* Process each of the options on the chain.  */
-  if (! ix86_valid_option_attribute_inner_p (args, option_strings))
+  if (! ix86_valid_target_attribute_inner_p (args, option_strings))
     return NULL_TREE;
 
   /* If the changed options are different from the default, rerun override_options,
@@ -3617,6 +3618,9 @@ ix86_valid_option_attribute_tree (tree a
       /* Do any overrides, such as arch=xxx, or tune=xxx support.  */
       override_options (false);
 
+      /* Add any builtin functions with the new isa if any.  */
+      ix86_add_new_builtins (ix86_isa_flags);
+
       /* Save the current options unless we are validating options for
 	 #pragma.  */
       t = build_target_option_node ();
@@ -3634,27 +3638,47 @@ ix86_valid_option_attribute_tree (tree a
   return t;
 }
 
-/* Hook to validate attribute((option("string"))).  */
+/* Hook to validate attribute((target("string"))).  */
 
 static bool
-ix86_valid_option_attribute_p (tree fndecl,
+ix86_valid_target_attribute_p (tree fndecl,
 			       tree ARG_UNUSED (name),
 			       tree args,
 			       int ARG_UNUSED (flags))
 {
-  struct cl_target_option cur_opts;
+  struct cl_target_option cur_target;
   bool ret = true;
-  tree new_opts;
+  tree old_optimize = build_optimization_node ();
+  tree new_target, new_optimize;
+  tree 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 (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);
+  new_target = ix86_valid_target_attribute_tree (args);
+  new_optimize = build_optimization_node ();
 
-  cl_target_option_save (&cur_opts);
-  new_opts = ix86_valid_option_attribute_tree (args);
-  if (!new_opts)
+  if (!new_target)
     ret = false;
 
   else if (fndecl)
-    DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_opts;
+    {
+      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
+
+      if (old_optimize != new_optimize)
+	DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+    }
+
+  cl_target_option_restore (&cur_target);
+
+  if (old_optimize != new_optimize)
+    cl_optimization_restore (TREE_OPTIMIZATION (old_optimize));
 
-  cl_target_option_restore (&cur_opts);
   return ret;
 }
 
@@ -19535,6 +19559,7 @@ enum ix86_builtins
   IX86_BUILTIN_FNMSUBSD,
   IX86_BUILTIN_FNMSUBPS,
   IX86_BUILTIN_FNMSUBPD,
+  IX86_BUILTIN_PCMOV,
   IX86_BUILTIN_PCMOV_V2DI,
   IX86_BUILTIN_PCMOV_V4SI,
   IX86_BUILTIN_PCMOV_V8HI,
@@ -19734,17 +19759,35 @@ enum ix86_builtins
 /* Table for the ix86 builtin decls.  */
 static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
 
-/* Table to record which ISA options the builtin needs.  */
-static int ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
+/* Table of all of the builtin functions that are possible with different ISA's
+   but are waiting to be built until a function is declared to use that
+   ISA.  */
+struct builtin_isa GTY(())
+{
+  tree type;			/* builtin type to use in the declaration */
+  const char *name;		/* function name */
+  int isa;			/* isa_flags this builtin is defined for */
+  bool const_p;			/* true if the declaration is constant */
+};
+
+static GTY(()) struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
+
 
 /* Add an ix86 target builtin function with CODE, NAME and TYPE.  Save the MASK
  * of which isa_flags to use in the ix86_builtins_isa array.  Stores the
  * function decl in the ix86_builtins array.  Returns the function decl or
  * NULL_TREE, if the builtin was not added.
  *
- * Record all builtins, even if it isn't an instruction set in the current ISA
- * in case the user uses function specific options for a different ISA.  When
- * the builtin is expanded, check at that time whether it is valid.  */
+ * If the front end has a special hook for builtin functions, delay adding
+ * builtin functions that aren't in the current ISA until the ISA is changed
+ * with function specific optimization.  Doing so, can save about 300K for the
+ * default compiler.  When the builtin is expanded, check at that time whether
+ * it is valid.
+ *
+ * If the front end doesn't have a special hook, record all builtins, even if
+ * it isn't an instruction set in the current ISA in case the user uses
+ * function specific options for a different ISA, so that we don't get scope
+ * errors if a builtin is added in the middle of a function scope.  */
 
 static inline tree
 def_builtin (int mask, const char *name, tree type, enum ix86_builtins code)
@@ -19753,10 +19796,25 @@ def_builtin (int mask, const char *name,
 
   if (!(mask & OPTION_MASK_ISA_64BIT) || TARGET_64BIT)
     {
-      decl = add_builtin_function (name, type, code, BUILT_IN_MD,
-				   NULL, NULL_TREE);
-      ix86_builtins[(int) code] = decl;
-      ix86_builtins_isa[(int) code] = mask;
+      ix86_builtins_isa[(int) code].isa = mask;
+
+      if ((mask & ix86_isa_flags) != 0
+	  || (lang_hooks.builtin_function
+	      == lang_hooks.builtin_function_ext_scope))
+
+	{
+	  decl = add_builtin_function (name, type, code, BUILT_IN_MD, NULL,
+				       NULL_TREE);
+	  ix86_builtins[(int) code] = decl;
+	  ix86_builtins_isa[(int) code].type = NULL_TREE;
+	}
+      else
+	{
+	  ix86_builtins[(int) code] = NULL_TREE;
+	  ix86_builtins_isa[(int) code].const_p = false;
+	  ix86_builtins_isa[(int) code].type = type;
+	  ix86_builtins_isa[(int) code].name = name;
+	}
     }
 
   return decl;
@@ -19771,9 +19829,40 @@ def_builtin_const (int mask, const char 
   tree decl = def_builtin (mask, name, type, code);
   if (decl)
     TREE_READONLY (decl) = 1;
+  else
+    ix86_builtins_isa[(int) code].const_p = true;
+
   return decl;
 }
 
+/* Add any new builtin functions for a given ISA that may not have been
+   declared.  This saves a bit of space compared to adding all of the
+   declarations to the tree, even if we didn't use them.  */
+
+static void
+ix86_add_new_builtins (int isa)
+{
+  int i;
+  tree decl;
+
+  for (i = 0; i < (int)IX86_BUILTIN_MAX; i++)
+    {
+      if ((ix86_builtins_isa[i].isa & isa) != 0
+	  && ix86_builtins_isa[i].type != NULL_TREE)
+	{
+	  decl = add_builtin_function_ext_scope (ix86_builtins_isa[i].name,
+						 ix86_builtins_isa[i].type,
+						 i, BUILT_IN_MD, NULL,
+						 NULL_TREE);
+
+	  ix86_builtins[i] = decl;
+	  ix86_builtins_isa[i].type = NULL_TREE;
+	  if (ix86_builtins_isa[i].const_p)
+	    TREE_READONLY (decl) = 1;
+	}
+    }
+}
+
 /* Bits for builtin_description.flag.  */
 
 /* Set when we don't support the comparison natively, and should
@@ -20787,7 +20876,7 @@ static const struct builtin_description 
   { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5i_vmfnmsubv2df4,    "__builtin_ia32_fnmsubsd",   IX86_BUILTIN_FNMSUBSD,   0,            (int)MULTI_ARG_3_DF },
   { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5i_fnmsubv4sf4,      "__builtin_ia32_fnmsubps",   IX86_BUILTIN_FNMSUBPS,   0,            (int)MULTI_ARG_3_SF },
   { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5i_fnmsubv2df4,      "__builtin_ia32_fnmsubpd",   IX86_BUILTIN_FNMSUBPD,   0,            (int)MULTI_ARG_3_DF },
-  { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5_pcmov_v2di,        "__builtin_ia32_pcmov",      IX86_BUILTIN_PCMOV_V2DI, 0,            (int)MULTI_ARG_3_DI },
+  { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5_pcmov_v2di,        "__builtin_ia32_pcmov",      IX86_BUILTIN_PCMOV,	 0,            (int)MULTI_ARG_3_DI },
   { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5_pcmov_v2di,        "__builtin_ia32_pcmov_v2di", IX86_BUILTIN_PCMOV_V2DI, 0,            (int)MULTI_ARG_3_DI },
   { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5_pcmov_v4si,        "__builtin_ia32_pcmov_v4si", IX86_BUILTIN_PCMOV_V4SI, 0,            (int)MULTI_ARG_3_SI },
   { OPTION_MASK_ISA_SSE5, CODE_FOR_sse5_pcmov_v8hi,        "__builtin_ia32_pcmov_v8hi", IX86_BUILTIN_PCMOV_V8HI, 0,            (int)MULTI_ARG_3_HI },
@@ -23986,10 +24075,10 @@ ix86_expand_builtin (tree exp, rtx targe
      current ISA based on the command line switches.  With function specific
      options, we need to check in the context of the function making the call
      whether it is supported.  */
-  if (ix86_builtins_isa[fcode]
-      && !(ix86_builtins_isa[fcode] & ix86_isa_flags))
+  if (ix86_builtins_isa[fcode].isa
+      && !(ix86_builtins_isa[fcode].isa & ix86_isa_flags))
     {
-      char *opts = ix86_target_string (ix86_builtins_isa[fcode], 0, NULL,
+      char *opts = ix86_target_string (ix86_builtins_isa[fcode].isa, 0, NULL,
 				       NULL, NULL, false);
 
       if (!opts)
@@ -29026,7 +29115,7 @@ ix86_enum_va_list (int idx, const char *
 #define TARGET_SET_CURRENT_FUNCTION ix86_set_current_function
 
 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
-#define TARGET_OPTION_VALID_ATTRIBUTE_P ix86_valid_option_attribute_p
+#define TARGET_OPTION_VALID_ATTRIBUTE_P ix86_valid_target_attribute_p
 
 #undef TARGET_OPTION_SAVE
 #define TARGET_OPTION_SAVE ix86_function_specific_save
@@ -29040,12 +29129,6 @@ ix86_enum_va_list (int idx, const char *
 #undef TARGET_OPTION_CAN_INLINE_P
 #define TARGET_OPTION_CAN_INLINE_P ix86_can_inline_p
 
-#undef TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION
-#define TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION true
-
-#undef TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION
-#define TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION true
-
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-i386.h"
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 139809)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -493,12 +493,6 @@ static const struct attribute_spec ia64_
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX ia64_c_mode_for_suffix
 
-#undef TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION
-#define TARGET_OPTION_COLD_ATTRIBUTE_SETS_OPTIMIZATION true
-
-#undef TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION
-#define TARGET_OPTION_HOT_ATTRIBUTE_SETS_OPTIMIZATION true
-
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 typedef enum
Index: gcc/langhooks-def.h
===================================================================
--- gcc/langhooks-def.h	(revision 139809)
+++ gcc/langhooks-def.h	(working copy)
@@ -112,6 +112,7 @@ extern void lhd_omp_firstprivatize_type_
 #define LANG_HOOKS_TREE_SIZE		lhd_tree_size
 #define LANG_HOOKS_TYPES_COMPATIBLE_P	lhd_types_compatible_p
 #define LANG_HOOKS_BUILTIN_FUNCTION	lhd_builtin_function
+#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE	LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_EXPR_TO_DECL		lhd_expr_to_decl
 #define LANG_HOOKS_TO_TARGET_CHARSET	lhd_to_target_charset
 #define LANG_HOOKS_INIT_TS		lhd_do_nothing
@@ -272,6 +273,7 @@ extern tree lhd_make_node (enum tree_cod
   LANG_HOOKS_GIMPLIFY_EXPR, \
   LANG_HOOKS_FOLD_OBJ_TYPE_REF, \
   LANG_HOOKS_BUILTIN_FUNCTION, \
+  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
   LANG_HOOKS_INIT_TS,          \
   LANG_HOOKS_EXPR_TO_DECL, \
 }


-- 
Michael Meissner
email: gnu@the-meissners.org
http://www.the-meissners.org


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]