aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2010-11-19 17:27:18 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2010-11-19 17:27:18 +0000
commitfd438373cdd2a5b12d2c17b77922ee8fb8d43847 (patch)
tree331042dabc400c80ac08ddae1835f9a3e6300ccc /gcc
parent69ccdddbb807489bdc6f25871532b6f8e236f82f (diff)
downloadgcc-fd438373cdd2a5b12d2c17b77922ee8fb8d43847.zip
gcc-fd438373cdd2a5b12d2c17b77922ee8fb8d43847.tar.gz
gcc-fd438373cdd2a5b12d2c17b77922ee8fb8d43847.tar.bz2
Add PowerPC target attribute/pragma support
From-SVN: r166947
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog227
-rw-r--r--gcc/Makefile.in17
-rw-r--r--gcc/config/rs6000/aix.opt2
-rw-r--r--gcc/config/rs6000/aix64.opt2
-rw-r--r--gcc/config/rs6000/linux64.h9
-rw-r--r--gcc/config/rs6000/linux64.opt2
-rw-r--r--gcc/config/rs6000/rs6000-opts.h144
-rw-r--r--gcc/config/rs6000/rs6000-protos.h3
-rw-r--r--gcc/config/rs6000/rs6000.c1689
-rw-r--r--gcc/config/rs6000/rs6000.h151
-rw-r--r--gcc/config/rs6000/rs6000.opt187
-rw-r--r--gcc/config/rs6000/sysv4.h14
-rw-r--r--gcc/config/rs6000/sysv4.opt12
-rwxr-xr-xgcc/configure19
-rw-r--r--gcc/configure.ac12
-rw-r--r--gcc/doc/extend.texi200
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/doc/options.texi26
-rw-r--r--gcc/opt-include.awk30
-rw-r--r--gcc/optc-gen.awk89
-rw-r--r--gcc/opth-gen.awk63
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-1.c59
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-2.c41
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-3.c62
25 files changed, 2376 insertions, 698 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 31ace53..292fa37 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,230 @@
+2010-11-19 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/extend.texi (Function attributes): Document PowerPC target
+ attributes that are supported.
+ (Pragmas): Document that PowerPC now supports target pragmas.
+
+ * doc/options.texi (TargetVariable): Document TargetVariable,
+ HeaderInclude, and SourceInclude.
+
+ * doc/invoke.texi (-mfused-madd): Document that -mfused-madd is
+ mapped to -ffp-contract=fast, and -mno-fused-madd is mapped to
+ -ffp-contract=off.
+
+ * optc-gen.awk: Add support for TargetVariable, HeaderInclude, and
+ SourceInclude directives. Fix a cut+paste error with target save
+ enum variables. Sort enums in the structures after ints and
+ before shorts.
+ * opth-gen.awk: Ditto.
+
+ * configure.ac: Add support for HeaderInclude and SourceInclude
+ option directives to add the appropriate files to the dependency
+ lists.
+ * configure: Regenerate.
+ * Makefile.in (OPTIONS_H_EXTRA): New variable for HeaderInclude.
+ (OPTIONS_C_EXTRA): New variable for SourceInclude.
+ (OPTIONS_H): Add $(OPTIONS_H_EXTRA).
+ (options.o): Add $(OPTIONS_C_EXTRA) dependency.
+ (gcc-options.o): Ditto.
+ * opt-include.awk: New awk script to handle HeaderInclude and
+ TargetInclude.
+
+ * config/rs6000/aix.opt (-mxl-compat): Mark option as Save so it
+ gets saved in the target options.
+ * config/rs6000/linux64.opt (-mprofile-kernel): Ditto.
+ * config/rs6000/sysv4.opt (-mbit-align): Ditto.
+ (-mprototype): Ditto.
+ (-mbit-word): ditto.
+ (-mregnames): Ditto.
+ (-msecure-plt): Ditto.
+ (-mbss-plt): Ditto.
+ * config/rs6000/rs6000.opt (-mpowerpc-gpopt): Ditto.
+ (-mpowerpc-gfxopt): Ditto.
+ (-mmfcrf): Ditto.
+ (-mpopcntb): Ditto.
+ (-mfprnd): Ditto.
+ (-mcmpb): Ditto.
+ (-mmmfpgpr): Ditto.
+ (-maltivec): Ditto.
+ (-mhard-dfp): Ditto.
+ (-mmulhw): Ditto.
+ (-mdlmzb): Ditto.
+ (-mmultiple): Ditto.
+ (-mstring): Ditto.
+ (-mpopcntd): Ditto.
+ (-mfriz): Ditto.
+ (-mvsx): Ditto.
+ (-mno-update): Ditto.
+ (-mavoid-indexed-addresses): Ditto.
+ (-mtls-markers): Ditto.
+ (-msched-epilog): Ditto.
+ (-msched-prolog): Ditto.
+ (-maix-struct-return): Ditto.
+ (-msvr4-struct-return): Ditto.
+ (-mxl-compat): Ditto.
+ (-mrecip-precision): Ditto.
+ (-mfp-in-toc): Ditto.
+ (-msum-in-toc): Ditto.
+ (-mvrsave): Ditto.
+ (-mblock-move-inline-limit=): Ditto.
+ (-misel): Ditto.
+ (-mpaired): Ditto.
+ (-mlongcall): Ditto.
+ (-mgen-cell-microcode): Ditto.
+ (-mwarn-cell-microcode): Ditto.
+ (-mwarn-altivec-long): Ditto.
+ (-mprioritize-restricted-insns=): Ditto.
+ (-msingle-float): Ditto.
+ (-mdouble-float): Ditto.
+ (-msimple-fpu): Ditto.
+ (-mxilinx-fpu): Ditto.
+ * config/rs6000/aix64.opt (-mpe): Ditto.
+
+ * config/rs6000/rs6000.opt (HeaderInclude): Include rs6000-opts.h.
+ (rs6000_cpu): Move variable to be a target variable. Rename
+ cmodel to rs6000_current_cmodel because of macro conflict. Merge
+ -mdebug=<xxx> variables into a single int.
+ (rs6000_always_hint): Ditto.
+ (rs6000_sched_groups): Ditto.
+ (rs6000_align_branch_targets): Ditto.
+ (rs6000_sched_costly_dep): Ditto.
+ (rs6000_sched_insert_nops): Ditto.
+ (rs6000_long_double_type_size): Ditto.
+ (rs6000_ieeequad): Ditto.
+ (rs6000_altivec_abi): Ditto.
+ (rs6000_spe): Ditto.
+ (rs6000_spe_abi): Ditto.
+ (rs6000_float_gprs): Ditto.
+ (rs6000_darwin64_abi): Ditto.
+ (can_override_loop_align): Ditto.
+ (rs6000_sdata): Ditto.
+ (rs6000_tls_size): Ditto.
+ (rs6000_current_abi): Ditto.
+ (rs6000_traceback): Ditto.
+ (rs6000_alignment_flags): Ditto.
+ (rs6000_current_cmodel): Ditto.
+ (rs6000_recip_control): Ditto.
+ (rs6000_cpu_index): Ditto.
+ (rs6000_tune_index): Ditto.
+ (rs6000_debug): Ditto.
+ (rs6000_target_flags_explict): Ditto.
+
+ * config/rs6000/rs6000-protos.h (rs6000_pragma_target_parse): Add
+ declaration.
+
+ * config/rs6000/linux64.h (rs6000_current_cmode): Rename from
+ cmodel. Change all uses.
+
+ * config/rs6000/rs6000.c (rs6000_always_hint): Move to
+ rs6000.opt. Combine -mdebug=<xxx> variables into a single int.
+ Rename cmodel to rs6000_current_cmodel.
+ (rs6000_sched_groups): Ditto.
+ (rs6000_align_branch_targets): Ditto.
+ (rs6000_sched_costly_dep): Ditto.
+ (rs6000_sched_insert_nops): Ditto.
+ (rs6000_long_double_type_size): Ditto.
+ (rs6000_ieeequad): Ditto.
+ (rs6000_altivec_abi): Ditto.
+ (rs6000_spe): Ditto.
+ (rs6000_spe_abi): Ditto.
+ (rs6000_float_gprs): Ditto.
+ (rs6000_darwin64_abi): Ditto.
+ (can_override_loop_align): Ditto.
+ (rs6000_sdata): Ditto.
+ (rs6000_tls_size): Ditto.
+ (rs6000_current_abi): Ditto.
+ (rs6000_traceback): Ditto.
+ (rs6000_alignment_flags): Ditto.
+ (rs6000_current_cmodel): Ditto.
+ (rs6000_recip_control): Ditto.
+ (rs6000_cpu_index): Ditto.
+ (rs6000_tune_index): Ditto.
+ (rs6000_debug): Ditto.
+ (rs6000_target_flags_explict): Ditto.
+ (rs6000_sched_insert_nops_str): Make static.
+ (rs6000_sched_costly_dep_str): Ditto.
+ (rs6000_recip_name): Ditto.
+ (rs6000_abi_name): Ditto.
+ (rs6000_sdata_name): Ditto.
+ (enum rs6000_traceback_name): Move to rs6000-opts.h.
+ (rs6000_parse_tls_size_option): Delete.
+ (rs6000_valid_attribute_p): New function for target attributes and
+ pragmas.
+ (rs6000_function_specific_save): Ditto.
+ (rs6000_function_specific_restore): Ditto.
+ (rs6000_function_specific_print): Ditto.
+ (rs6000_can_inline_p): Ditto.
+ (rs6000_set_current_function): Ditto.
+ (rs6000_inner_target_options): Ditto.
+ (rs6000_debug_target_options): Ditto.
+ (rs6000_pragma_target_parse): Ditto.
+ (TARGET_OPTION_VALID_ATTRIBUTE_P): Define target hooks for target
+ attributes and pragmas.
+ (TARGET_OPTION_SAVE): Ditto.
+ (TARGET_OPTION_RESTORE): Ditto.
+ (TARGET_OPTION_PRINT): Ditto.
+ (TARGET_CAN_INLINE_P): Ditto.
+ (TARGET_SET_CURRENT_FUNCTION): Ditto.
+ (POWER_MASKS): Move to file level scope from the
+ rs6000_option_override_internal function.
+ (POWERPC_MASKS): Ditto.
+ (ISA_*_MASKS): Ditto.
+ (struct rs6000_ptt): Ditto.
+ (processor_target_table): Ditto.
+ (rs6000_cpu_name_lookup): Map cpu name to an index in
+ processor_target_table.
+ (rs6000_debug_reg_global): Print more information on processor
+ options for -mdebug=reg.
+ (rs6000_init_hard_regno_mode_ok): Add support for target
+ attributes and pragmas. Merge all -mdebug=<xxx> fields into one.
+ Allow -mdebug=val1,val2. Rename cmodel variable.
+ (rs6000_option_override_internal): Ditto.
+ (rs6000_option_override): Ditto.
+ (rs6000_handle_option): Ditto.
+ (rs6000_conditional_register_usage): Add debug trace message.
+ (struct rs6000_opt_mask): New for target attribute/pragma
+ support.
+ (rs6000_opt_masks): Ditto.
+ (struct rs6000_opt_var): Ditto.
+ (rs6000_opt_vars): Ditto.
+ (rs6000_previous_function): Ditto.
+
+ * config/rs6000/rs6000.h (top level): Include rs6000-opts.h if it
+ wasn't already included.
+ (enum rs6000_cmodel): Move to rs6000-opts.h or rs6000.opt.
+ (enum processor_type): Ditto.
+ (rs6000_cpu): Ditto.
+ (enum fpu_type_t): Ditto.
+ (fpu_type): Ditto.
+ (enum rs6000_dependence_cost): Ditto.
+ (enum rs6000_nop_insertion): Ditto.
+ (enum group_termination): Ditto.
+ (rs6000_long_double_type_size): Ditto.
+ (rs6000_ieeequad): Ditto.
+ (rs6000_altivec_abi): Ditto.
+ (rs6000_spe_abi): Ditto.
+ (rs6000_spe): Ditto.
+ (rs6000_float_gprs): Ditto.
+ (rs6000_alignment_flags): Ditto.
+ (rs6000_sched_insert_nops): Ditto.
+ (enum rs6000_vector): Ditto.
+ (enum rs6000_abi): Ditto.
+ (rs6000_current_opt): Ditto.
+ (rs6000_debug_*): Delete.
+ (MASK_DEBUG*): Combine -mdebug=xxxx into one int.
+ (TARGET_DEBUG*): Ditto.
+
+ * config/rs6000/rs6000-opts.h: New header file to define the enums
+ that are used in target variables that are now defined in
+ rs6000.opt.
+
+ * config/rs6000/sysv4.h (enum rs6000_sdata_type): Move to
+ rs6000-opts.h.
+ (rs6000_sdata): Ditto.
+ (rs6000_abi_name): Delete.
+ (rs6000_sdata_name): Ditto.
+ (rs6000_tls_size_string): Ditto.
+
2010-11-19 Joseph Myers <joseph@codesourcery.com>
* common.opt (debug_struct_ordinary, debug_struct_generic): New
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 2904da3..5491aeaf 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -806,6 +806,16 @@ T_TARGET : $(T_TARGET)
# at build time.
SPECS = specs
+# Extra include files that are defined by HeaderInclude directives in
+# the .opt files
+OPTIONS_H_EXTRA =
+
+# Extra include files that are defined by SourceInclude directives in
+# the .opt files
+OPTIONS_C_EXTRA =
+
+@option_includes@
+
# End of variables for you to override.
# GTM_H lists the config files that the generator files depend on,
@@ -893,7 +903,7 @@ RECOG_H = recog.h
ALIAS_H = alias.h coretypes.h
EMIT_RTL_H = emit-rtl.h
FLAGS_H = flags.h coretypes.h flag-types.h $(OPTIONS_H)
-OPTIONS_H = options.h flag-types.h
+OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H) vecprim.h $(TM_H)
EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
OPTABS_H = optabs.h insn-codes.h
@@ -2234,9 +2244,10 @@ s-options-h: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opth-gen.awk
$(STAMP) $@
options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(FLAGS_H) \
- $(TM_H) $(OPTS_H) intl.h
+ $(TM_H) $(OPTS_H) intl.h $(OPTIONS_C_EXTRA)
-gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OPTS_H) intl.h
+gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OPTS_H) intl.h \
+ $(OPTIONS_C_EXTRA)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) \
-DGCC_DRIVER options.c
diff --git a/gcc/config/rs6000/aix.opt b/gcc/config/rs6000/aix.opt
index d000172..ac2b603 100644
--- a/gcc/config/rs6000/aix.opt
+++ b/gcc/config/rs6000/aix.opt
@@ -20,5 +20,5 @@
; <http://www.gnu.org/licenses/>.
mxl-compat
-Target Var(has_xl_compat_option)
+Target Var(has_xl_compat_option) Save
Conform more closely to IBM XLC semantics
diff --git a/gcc/config/rs6000/aix64.opt b/gcc/config/rs6000/aix64.opt
index 2ffcff6..230bb99 100644
--- a/gcc/config/rs6000/aix64.opt
+++ b/gcc/config/rs6000/aix64.opt
@@ -28,5 +28,5 @@ Target Report RejectNegative Negative(maix64) InverseMask(64BIT)
Compile for 32-bit pointers
mpe
-Target Report RejectNegative Var(internal_nothing_1)
+Target Report RejectNegative Var(internal_nothing_1) Save
Support message passing with the Parallel Environment
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index b233261..0bc774a 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -65,10 +65,9 @@ extern int dot_symbols;
#define TARGET_USES_LINUX64_OPT 1
#ifdef HAVE_LD_LARGE_TOC
-extern enum rs6000_cmodel cmodel;
#undef TARGET_CMODEL
-#define TARGET_CMODEL cmodel
-#define SET_CMODEL(opt) cmodel = opt
+#define TARGET_CMODEL rs6000_current_cmodel
+#define SET_CMODEL(opt) rs6000_current_cmodel = opt
#else
#define SET_CMODEL(opt) do {} while (0)
#endif
@@ -127,7 +126,7 @@ extern enum rs6000_cmodel cmodel;
if ((target_flags_explicit & MASK_MINIMAL_TOC) != 0) \
{ \
if (rs6000_explicit_options.cmodel \
- && cmodel != CMODEL_SMALL) \
+ && rs6000_current_cmodel != CMODEL_SMALL) \
error ("-mcmodel incompatible with other toc options"); \
SET_CMODEL (CMODEL_SMALL); \
} \
@@ -135,7 +134,7 @@ extern enum rs6000_cmodel cmodel;
{ \
if (!rs6000_explicit_options.cmodel) \
SET_CMODEL (CMODEL_MEDIUM); \
- if (cmodel != CMODEL_SMALL) \
+ if (rs6000_current_cmodel != CMODEL_SMALL) \
{ \
TARGET_NO_FP_IN_TOC = 0; \
TARGET_NO_SUM_IN_TOC = 0; \
diff --git a/gcc/config/rs6000/linux64.opt b/gcc/config/rs6000/linux64.opt
index 9d0e26a..28177f1 100644
--- a/gcc/config/rs6000/linux64.opt
+++ b/gcc/config/rs6000/linux64.opt
@@ -20,7 +20,7 @@
; <http://www.gnu.org/licenses/>.
mprofile-kernel
-Target Report Var(profile_kernel)
+Target Report Var(profile_kernel) Save
Call mcount for profiling before a function prologue
mcmodel=
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
new file mode 100644
index 0000000..542fea7
--- /dev/null
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -0,0 +1,144 @@
+/* Definitions of target machine needed for option handling for GNU compiler,
+ for IBM RS/6000.
+ Copyright (C) 2010
+ Free Software Foundation, Inc.
+ Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef RS6000_OPTS_H
+#define RS6000_OPTS_H
+
+/* Processor type. Order must match cpu attribute in MD file. */
+enum processor_type
+ {
+ PROCESSOR_RIOS1,
+ PROCESSOR_RIOS2,
+ PROCESSOR_RS64A,
+ PROCESSOR_MPCCORE,
+ PROCESSOR_PPC403,
+ PROCESSOR_PPC405,
+ PROCESSOR_PPC440,
+ PROCESSOR_PPC476,
+ PROCESSOR_PPC601,
+ PROCESSOR_PPC603,
+ PROCESSOR_PPC604,
+ PROCESSOR_PPC604e,
+ PROCESSOR_PPC620,
+ PROCESSOR_PPC630,
+ PROCESSOR_PPC750,
+ PROCESSOR_PPC7400,
+ PROCESSOR_PPC7450,
+ PROCESSOR_PPC8540,
+ PROCESSOR_PPCE300C2,
+ PROCESSOR_PPCE300C3,
+ PROCESSOR_PPCE500MC,
+ PROCESSOR_PPCE500MC64,
+ PROCESSOR_POWER4,
+ PROCESSOR_POWER5,
+ PROCESSOR_POWER6,
+ PROCESSOR_POWER7,
+ PROCESSOR_CELL,
+ PROCESSOR_PPCA2,
+ PROCESSOR_TITAN
+};
+
+/* FP processor type. */
+enum fpu_type_t
+{
+ FPU_NONE, /* No FPU */
+ FPU_SF_LITE, /* Limited Single Precision FPU */
+ FPU_DF_LITE, /* Limited Double Precision FPU */
+ FPU_SF_FULL, /* Full Single Precision FPU */
+ FPU_DF_FULL /* Full Double Single Precision FPU */
+};
+
+/* Types of costly dependences. */
+enum rs6000_dependence_cost
+{
+ max_dep_latency = 1000,
+ no_dep_costly,
+ all_deps_costly,
+ true_store_to_load_dep_costly,
+ store_to_load_dep_costly
+};
+
+/* Types of nop insertion schemes in sched target hook sched_finish. */
+enum rs6000_nop_insertion
+{
+ sched_finish_regroup_exact = 1000,
+ sched_finish_pad_groups,
+ sched_finish_none
+};
+
+/* Dispatch group termination caused by an insn. */
+enum group_termination
+{
+ current_group,
+ previous_group
+};
+
+/* Enumeration to give which calling sequence to use. */
+enum rs6000_abi {
+ ABI_NONE,
+ ABI_AIX, /* IBM's AIX */
+ ABI_V4, /* System V.4/eabi */
+ ABI_DARWIN /* Apple's Darwin (OS X kernel) */
+};
+
+/* Small data support types. */
+enum rs6000_sdata_type {
+ SDATA_NONE, /* No small data support. */
+ SDATA_DATA, /* Just put data in .sbss/.sdata, don't use relocs. */
+ SDATA_SYSV, /* Use r13 to point to .sdata/.sbss. */
+ SDATA_EABI /* Use r13 like above, r2 points to .sdata2/.sbss2. */
+};
+
+/* Type of traceback to use. */
+enum rs6000_traceback_type {
+ traceback_default = 0,
+ traceback_none,
+ traceback_part,
+ traceback_full
+};
+
+/* Code model for 64-bit linux.
+ small: 16-bit toc offsets.
+ medium: 32-bit toc offsets, static data and code within 2G of TOC pointer.
+ large: 32-bit toc offsets, no limit on static data and code. */
+enum rs6000_cmodel {
+ CMODEL_SMALL,
+ CMODEL_MEDIUM,
+ CMODEL_LARGE
+};
+
+/* Describe which vector unit to use for a given machine mode. */
+enum rs6000_vector {
+ VECTOR_NONE, /* Type is not a vector or not supported */
+ VECTOR_ALTIVEC, /* Use altivec for vector processing */
+ VECTOR_VSX, /* Use VSX for vector processing */
+ VECTOR_PAIRED, /* Use paired floating point for vectors */
+ VECTOR_SPE, /* Use SPE for vector processing */
+ VECTOR_OTHER /* Some other vector unit */
+};
+
+#endif
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 40e8acb..ebf896f 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -175,6 +175,9 @@ extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
extern void rs6000_pragma_longcall (struct cpp_reader *);
extern void rs6000_cpu_cpp_builtins (struct cpp_reader *);
+#ifdef TREE_CODE
+extern bool rs6000_pragma_target_parse (tree, tree);
+#endif
#if TARGET_MACHO
char *output_call (rtx, rtx *, int, int);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index fe3d0db..cdc7272 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -139,7 +139,6 @@ typedef struct GTY(()) machine_function
/* Target cpu type */
-enum processor_type rs6000_cpu;
struct rs6000_cpu_select rs6000_select[3] =
{
/* switch name, tune arch */
@@ -148,50 +147,19 @@ struct rs6000_cpu_select rs6000_select[3] =
{ (const char *)0, "-mtune=", 1, 0 },
};
-/* Always emit branch hint bits. */
-static GTY(()) bool rs6000_always_hint;
-
-/* Schedule instructions for group formation. */
-static GTY(()) bool rs6000_sched_groups;
-
-/* Align branch targets. */
-static GTY(()) bool rs6000_align_branch_targets;
-
-/* Non-zero to allow overriding loop alignment. */
-static int can_override_loop_align = 0;
-
-/* Support for -msched-costly-dep option. */
-const char *rs6000_sched_costly_dep_str;
-enum rs6000_dependence_cost rs6000_sched_costly_dep;
+/* String variables to hold the various options. */
+static const char *rs6000_sched_insert_nops_str;
+static const char *rs6000_sched_costly_dep_str;
+static const char *rs6000_recip_name;
-/* Support for -minsert-sched-nops option. */
-const char *rs6000_sched_insert_nops_str;
-enum rs6000_nop_insertion rs6000_sched_insert_nops;
+#ifdef USING_ELFOS_H
+static const char *rs6000_abi_name;
+static const char *rs6000_sdata_name;
+#endif
/* Support targetm.vectorize.builtin_mask_for_load. */
static GTY(()) tree altivec_builtin_mask_for_load;
-/* Size of long double. */
-int rs6000_long_double_type_size;
-
-/* IEEE quad extended precision long double. */
-int rs6000_ieeequad;
-
-/* Nonzero to use AltiVec ABI. */
-int rs6000_altivec_abi;
-
-/* Nonzero if we want SPE SIMD instructions. */
-int rs6000_spe;
-
-/* Nonzero if we want SPE ABI extensions. */
-int rs6000_spe_abi;
-
-/* Nonzero if floating point operations are done in the GPRs. */
-int rs6000_float_gprs = 0;
-
-/* Nonzero if we want Darwin's struct-by-value-in-regs ABI. */
-int rs6000_darwin64_abi;
-
/* Set to nonzero once AIX common-mode calls have been defined. */
static GTY(()) int common_mode_defined;
@@ -200,37 +168,13 @@ static GTY(()) int common_mode_defined;
static int rs6000_pic_labelno;
#ifdef USING_ELFOS_H
-/* Which abi to adhere to */
-const char *rs6000_abi_name;
-
-/* Semantics of the small data area */
-enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;
-
-/* Which small data model to use */
-const char *rs6000_sdata_name = (char *)0;
-
/* Counter for labels which are to be placed in .fixup. */
int fixuplabelno = 0;
#endif
-/* Bit size of immediate TLS offsets and string from which it is decoded. */
-int rs6000_tls_size = 32;
-const char *rs6000_tls_size_string;
-
-/* ABI enumeration available for subtarget to use. */
-enum rs6000_abi rs6000_current_abi;
-
/* Whether to use variant of AIX ABI for PowerPC64 Linux. */
int dot_symbols;
-/* Debug flags */
-const char *rs6000_debug_name;
-int rs6000_debug_stack; /* debug stack applications */
-int rs6000_debug_arg; /* debug argument handling */
-int rs6000_debug_reg; /* debug register classes */
-int rs6000_debug_addr; /* debug memory addressing */
-int rs6000_debug_cost; /* debug rtx_costs */
-
/* Specify the machine mode that pointers have. After generation of rtl, the
compiler makes no further distinction between pointers and any other objects
of this machine mode. The type is unsigned since not all things that
@@ -260,14 +204,6 @@ static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2];
tree rs6000_builtin_types[RS6000_BTI_MAX];
tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
-const char *rs6000_traceback_name;
-static enum {
- traceback_default = 0,
- traceback_none,
- traceback_part,
- traceback_full
-} rs6000_traceback;
-
/* Flag to say the TOC is initialized */
int toc_initialized;
char toc_label_name[10];
@@ -282,13 +218,6 @@ static GTY(()) section *read_only_private_data_section;
static GTY(()) section *sdata2_section;
static GTY(()) section *toc_section;
-/* Control alignment for fields within structures. */
-/* String from -malign-XXXXX. */
-int rs6000_alignment_flags;
-
-/* Code model for 64-bit linux. */
-enum rs6000_cmodel cmodel;
-
/* True for any options that were explicitly set. */
static struct {
bool aix_struct_ret; /* True if -maix-struct-ret was used. */
@@ -358,9 +287,6 @@ enum rs6000_recip_mask {
RECIP_LOW_PRECISION = (RECIP_ALL & ~(RECIP_DF_RSQRT | RECIP_V2DF_RSQRT))
};
-static unsigned int rs6000_recip_control;
-static const char *rs6000_recip_name;
-
/* -mrecip options. */
static struct
{
@@ -1145,7 +1071,6 @@ static void rs6000_option_init_struct (struct gcc_options *);
static void rs6000_option_default_params (void);
static bool rs6000_handle_option (size_t, const char *, int);
static int rs6000_loop_align_max_skip (rtx);
-static void rs6000_parse_tls_size_option (void);
static void rs6000_parse_yes_no_option (const char *, const char *, int *);
static int first_altivec_reg_to_save (void);
static unsigned int compute_vrsave_mask (void);
@@ -1302,6 +1227,15 @@ struct GTY(()) builtin_hash_struct
};
static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table;
+
+static bool rs6000_valid_attribute_p (tree, tree, tree, int);
+static void rs6000_function_specific_save (struct cl_target_option *);
+static void rs6000_function_specific_restore (struct cl_target_option *);
+static void rs6000_function_specific_print (FILE *, int,
+ struct cl_target_option *);
+static bool rs6000_can_inline_p (tree, tree);
+static void rs6000_set_current_function (tree);
+
/* Default register names. */
char rs6000_reg_names[][8] =
@@ -1702,8 +1636,213 @@ static const struct default_options rs6000_option_optimization_table[] =
#undef TARGET_FUNCTION_VALUE
#define TARGET_FUNCTION_VALUE rs6000_function_value
+#undef TARGET_OPTION_VALID_ATTRIBUTE_P
+#define TARGET_OPTION_VALID_ATTRIBUTE_P rs6000_valid_attribute_p
+
+#undef TARGET_OPTION_SAVE
+#define TARGET_OPTION_SAVE rs6000_function_specific_save
+
+#undef TARGET_OPTION_RESTORE
+#define TARGET_OPTION_RESTORE rs6000_function_specific_restore
+
+#undef TARGET_OPTION_PRINT
+#define TARGET_OPTION_PRINT rs6000_function_specific_print
+
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P rs6000_can_inline_p
+
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION rs6000_set_current_function
+
struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Simplifications for entries below. */
+
+enum {
+ POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
+ POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC
+};
+
+/* Some OSs don't support saving the high part of 64-bit registers on context
+ switch. Other OSs don't support saving Altivec registers. On those OSs, we
+ don't touch the MASK_POWERPC64 or MASK_ALTIVEC settings; if the user wants
+ either, the user must explicitly specify them and we won't interfere with
+ the user's specification. */
+
+enum {
+ POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
+ POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
+ | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
+ | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
+ | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE
+ | MASK_RECIP_PRECISION)
+};
+
+/* Masks for instructions set at various powerpc ISAs. */
+enum {
+ ISA_2_1_MASKS = MASK_MFCRF,
+ ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB),
+ ISA_2_4_MASKS = (ISA_2_2_MASKS | MASK_FPRND),
+
+ /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't add
+ ALTIVEC, since in general it isn't a win on power6. In ISA 2.04, fsel,
+ fre, fsqrt, etc. were no longer documented as optional. Group masks by
+ server and embedded. */
+ ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION
+ | MASK_PPC_GFXOPT | MASK_PPC_GPOPT),
+ ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP),
+
+ /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
+ altivec is a win so enable it. */
+ ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD),
+ ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC
+ | MASK_VSX)
+};
+
+/* This table occasionally claims that a processor does not support a
+ particular feature even though it does, but the feature is slower than the
+ alternative. Thus, it shouldn't be relied on as a complete description of
+ the processor's support.
+
+ Please keep this list in order, and don't forget to update the documentation
+ in invoke.texi when adding a new processor or flag. */
+
+struct rs6000_ptt
+{
+ const char *const name; /* Canonical processor name. */
+ const enum processor_type processor; /* Processor type enum value. */
+ const int target_enable; /* Target flags to enable. */
+};
+
+static struct rs6000_ptt const processor_target_table[] =
+{
+ {"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"403", PROCESSOR_PPC403,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
+ {"405", PROCESSOR_PPC405,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+ {"405fp", PROCESSOR_PPC405,
+ POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+ {"440", PROCESSOR_PPC440,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+ {"440fp", PROCESSOR_PPC440,
+ POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+ {"464", PROCESSOR_PPC440,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+ {"464fp", PROCESSOR_PPC440,
+ POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+ {"476", PROCESSOR_PPC476,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF
+ | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
+ {"476fp", PROCESSOR_PPC476,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB
+ | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
+ {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
+ {"601", PROCESSOR_PPC601,
+ MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
+ {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"620", PROCESSOR_PPC620,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+ {"630", PROCESSOR_PPC630,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+ {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK},
+ {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK},
+ {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
+ | MASK_ISEL},
+ /* 8548 has a dummy entry for now. */
+ {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
+ | MASK_ISEL},
+ {"a2", PROCESSOR_PPCA2,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB
+ | MASK_CMPB | MASK_NO_UPDATE },
+ {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
+ {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
+ | MASK_ISEL},
+ {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
+ | MASK_PPC_GFXOPT | MASK_ISEL},
+ {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"970", PROCESSOR_POWER4,
+ POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+ {"cell", PROCESSOR_CELL,
+ POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+ {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS},
+ {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"G4", PROCESSOR_PPC7450, POWERPC_7400_MASK},
+ {"G5", PROCESSOR_POWER4,
+ POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+ {"titan", PROCESSOR_TITAN,
+ POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+ {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+ {"power2", PROCESSOR_POWER,
+ MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
+ {"power3", PROCESSOR_PPC630,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+ {"power4", PROCESSOR_POWER4,
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF},
+ {"power5", PROCESSOR_POWER5,
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB},
+ {"power5+", PROCESSOR_POWER5,
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
+ {"power6", PROCESSOR_POWER6,
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
+ | MASK_RECIP_PRECISION},
+ {"power6x", PROCESSOR_POWER6,
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
+ | MASK_MFPGPR | MASK_RECIP_PRECISION},
+ {"power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */
+ POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
+ | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
+ | MASK_VSX | MASK_RECIP_PRECISION},
+ {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
+ {"powerpc64", PROCESSOR_POWERPC64,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
+ {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+ {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+ {"rios2", PROCESSOR_RIOS2,
+ MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
+ {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+ {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
+ {"rs64", PROCESSOR_RS64A,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
+};
+
+/* Look up a processor name for -mcpu=xxx and -mtune=xxx. Return -1 if the
+ name is invalid. */
+
+static int
+rs6000_cpu_name_lookup (const char *name)
+{
+ size_t i;
+
+ if (name != NULL)
+ {
+ for (i = 0; i < ARRAY_SIZE (processor_target_table); i++)
+ if (! strcmp (name, processor_target_table[i].name))
+ return (int)i;
+ }
+
+ return -1;
+}
+
+
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
This is ordinarily the length in words of a value of mode MODE
@@ -1886,16 +2025,23 @@ rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
}
}
+#define DEBUG_FMT_D "%-32s= %d\n"
+#define DEBUG_FMT_S "%-32s= %s\n"
+
/* Print various interesting information with -mdebug=reg. */
static void
rs6000_debug_reg_global (void)
{
+ static const char *const tf[2] = { "false", "true" };
const char *nl = (const char *)0;
int m;
char costly_num[20];
char nop_num[20];
const char *costly_str;
const char *nop_str;
+ const char *trace_str;
+ const char *abi_str;
+ const char *cmodel_str;
/* Map enum rs6000_vector to string. */
static const char *rs6000_debug_vector_unit[] = {
@@ -1975,6 +2121,14 @@ rs6000_debug_reg_global (void)
fputs ("\n", stderr);
}
+ if (rs6000_cpu_index >= 0)
+ fprintf (stderr, DEBUG_FMT_S, "cpu",
+ processor_target_table[rs6000_cpu_index].name);
+
+ if (rs6000_tune_index >= 0)
+ fprintf (stderr, DEBUG_FMT_S, "tune",
+ processor_target_table[rs6000_tune_index].name);
+
switch (rs6000_sched_costly_dep)
{
case max_dep_latency:
@@ -2003,6 +2157,8 @@ rs6000_debug_reg_global (void)
break;
}
+ fprintf (stderr, DEBUG_FMT_S, "sched_costly_dep", costly_str);
+
switch (rs6000_sched_insert_nops)
{
case sched_finish_regroup_exact:
@@ -2023,21 +2179,85 @@ rs6000_debug_reg_global (void)
break;
}
- fprintf (stderr,
- "always_hint = %s\n"
- "align_branch_targets = %s\n"
- "sched_restricted_insns_priority = %d\n"
- "sched_costly_dep = %s\n"
- "sched_insert_nops = %s\n\n",
- rs6000_always_hint ? "true" : "false",
- rs6000_align_branch_targets ? "true" : "false",
- (int)rs6000_sched_restricted_insns_priority,
- costly_str, nop_str);
+ fprintf (stderr, DEBUG_FMT_S, "sched_insert_nops", nop_str);
+
+ switch (rs6000_sdata)
+ {
+ default:
+ case SDATA_NONE:
+ break;
+
+ case SDATA_DATA:
+ fprintf (stderr, DEBUG_FMT_S, "sdata", "data");
+ break;
+
+ case SDATA_SYSV:
+ fprintf (stderr, DEBUG_FMT_S, "sdata", "sysv");
+ break;
+
+ case SDATA_EABI:
+ fprintf (stderr, DEBUG_FMT_S, "sdata", "eabi");
+ break;
+
+ }
+
+ switch (rs6000_traceback)
+ {
+ case traceback_default: trace_str = "default"; break;
+ case traceback_none: trace_str = "none"; break;
+ case traceback_part: trace_str = "part"; break;
+ case traceback_full: trace_str = "full"; break;
+ default: trace_str = "unknown"; break;
+ }
+
+ fprintf (stderr, DEBUG_FMT_S, "traceback", trace_str);
+
+ switch (rs6000_current_cmodel)
+ {
+ case CMODEL_SMALL: cmodel_str = "small"; break;
+ case CMODEL_MEDIUM: cmodel_str = "medium"; break;
+ case CMODEL_LARGE: cmodel_str = "large"; break;
+ default: cmodel_str = "unknown"; break;
+ }
+
+ fprintf (stderr, DEBUG_FMT_S, "cmodel", cmodel_str);
+
+ switch (rs6000_current_abi)
+ {
+ case ABI_NONE: abi_str = "none"; break;
+ case ABI_AIX: abi_str = "aix"; break;
+ case ABI_V4: abi_str = "V4"; break;
+ case ABI_DARWIN: abi_str = "darwin"; break;
+ default: abi_str = "unknown"; break;
+ }
+
+ fprintf (stderr, DEBUG_FMT_S, "abi", abi_str);
+
+ if (rs6000_altivec_abi)
+ fprintf (stderr, DEBUG_FMT_S, "altivec_abi", "true");
+
+ if (rs6000_spe_abi)
+ fprintf (stderr, DEBUG_FMT_S, "spe_abi", "true");
+
+ if (rs6000_darwin64_abi)
+ fprintf (stderr, DEBUG_FMT_S, "darwin64_abi", "true");
+
+ if (rs6000_float_gprs)
+ fprintf (stderr, DEBUG_FMT_S, "float_gprs", "true");
+
+ fprintf (stderr, DEBUG_FMT_S, "always_hint", tf[!!rs6000_always_hint]);
+ fprintf (stderr, DEBUG_FMT_S, "align_branch",
+ tf[!!rs6000_align_branch_targets]);
+ fprintf (stderr, DEBUG_FMT_D, "tls_size", rs6000_tls_size);
+ fprintf (stderr, DEBUG_FMT_D, "long_double_size",
+ rs6000_long_double_type_size);
+ fprintf (stderr, DEBUG_FMT_D, "sched_restricted_insns_priority",
+ (int)rs6000_sched_restricted_insns_priority);
}
/* Initialize the various global tables that are based on register size. */
static void
-rs6000_init_hard_regno_mode_ok (void)
+rs6000_init_hard_regno_mode_ok (bool global_init_p)
{
int r, m, c;
int align64;
@@ -2330,40 +2550,43 @@ rs6000_init_hard_regno_mode_ok (void)
}
}
- if (TARGET_DEBUG_REG)
- rs6000_debug_reg_global ();
-
- if (TARGET_DEBUG_COST || TARGET_DEBUG_REG)
- fprintf (stderr,
- "SImode variable mult cost = %d\n"
- "SImode constant mult cost = %d\n"
- "SImode short constant mult cost = %d\n"
- "DImode multipliciation cost = %d\n"
- "SImode division cost = %d\n"
- "DImode division cost = %d\n"
- "Simple fp operation cost = %d\n"
- "DFmode multiplication cost = %d\n"
- "SFmode division cost = %d\n"
- "DFmode division cost = %d\n"
- "cache line size = %d\n"
- "l1 cache size = %d\n"
- "l2 cache size = %d\n"
- "simultaneous prefetches = %d\n"
- "\n",
- rs6000_cost->mulsi,
- rs6000_cost->mulsi_const,
- rs6000_cost->mulsi_const9,
- rs6000_cost->muldi,
- rs6000_cost->divsi,
- rs6000_cost->divdi,
- rs6000_cost->fp,
- rs6000_cost->dmul,
- rs6000_cost->sdiv,
- rs6000_cost->ddiv,
- rs6000_cost->cache_line_size,
- rs6000_cost->l1_cache_size,
- rs6000_cost->l2_cache_size,
- rs6000_cost->simultaneous_prefetches);
+ if (global_init_p || TARGET_DEBUG_TARGET)
+ {
+ if (TARGET_DEBUG_REG)
+ rs6000_debug_reg_global ();
+
+ if (TARGET_DEBUG_COST || TARGET_DEBUG_REG)
+ fprintf (stderr,
+ "SImode variable mult cost = %d\n"
+ "SImode constant mult cost = %d\n"
+ "SImode short constant mult cost = %d\n"
+ "DImode multipliciation cost = %d\n"
+ "SImode division cost = %d\n"
+ "DImode division cost = %d\n"
+ "Simple fp operation cost = %d\n"
+ "DFmode multiplication cost = %d\n"
+ "SFmode division cost = %d\n"
+ "DFmode division cost = %d\n"
+ "cache line size = %d\n"
+ "l1 cache size = %d\n"
+ "l2 cache size = %d\n"
+ "simultaneous prefetches = %d\n"
+ "\n",
+ rs6000_cost->mulsi,
+ rs6000_cost->mulsi_const,
+ rs6000_cost->mulsi_const9,
+ rs6000_cost->muldi,
+ rs6000_cost->divsi,
+ rs6000_cost->divdi,
+ rs6000_cost->fp,
+ rs6000_cost->dmul,
+ rs6000_cost->sdiv,
+ rs6000_cost->ddiv,
+ rs6000_cost->cache_line_size,
+ rs6000_cost->l1_cache_size,
+ rs6000_cost->l2_cache_size,
+ rs6000_cost->simultaneous_prefetches);
+ }
}
#if TARGET_MACHO
@@ -2420,187 +2643,26 @@ darwin_rs6000_override_options (void)
#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
#endif
-/* Override command line options. Mostly we process the processor
- type and sometimes adjust other TARGET_ options. */
+/* Override command line options. Mostly we process the processor type and
+ sometimes adjust other TARGET_ options. */
-static void
-rs6000_option_override_internal (const char *default_cpu)
+static bool
+rs6000_option_override_internal (bool global_init_p)
{
- size_t i, j;
- struct rs6000_cpu_select *ptr;
+ bool ret = true;
+ const char *default_cpu = OPTION_TARGET_CPU_DEFAULT;
int set_masks;
-
- /* Simplifications for entries below. */
-
- enum {
- POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
- POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC
- };
-
- /* This table occasionally claims that a processor does not support
- a particular feature even though it does, but the feature is slower
- than the alternative. Thus, it shouldn't be relied on as a
- complete description of the processor's support.
-
- Please keep this list in order, and don't forget to update the
- documentation in invoke.texi when adding a new processor or
- flag. */
- static struct ptt
- {
- const char *const name; /* Canonical processor name. */
- const enum processor_type processor; /* Processor type enum value. */
- const int target_enable; /* Target flags to enable. */
- } const processor_target_table[]
- = {{"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"403", PROCESSOR_PPC403,
- POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
- {"405", PROCESSOR_PPC405,
- POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
- {"405fp", PROCESSOR_PPC405,
- POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
- {"440", PROCESSOR_PPC440,
- POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
- {"440fp", PROCESSOR_PPC440,
- POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
- {"464", PROCESSOR_PPC440,
- POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
- {"464fp", PROCESSOR_PPC440,
- POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
- {"476", PROCESSOR_PPC476,
- POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF
- | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
- {"476fp", PROCESSOR_PPC476,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB
- | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
- {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
- {"601", PROCESSOR_PPC601,
- MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
- {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"620", PROCESSOR_PPC620,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
- {"630", PROCESSOR_PPC630,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
- {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK},
- {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK},
- {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
- | MASK_ISEL},
- /* 8548 has a dummy entry for now. */
- {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
- | MASK_ISEL},
- {"a2", PROCESSOR_PPCA2,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB
- | MASK_CMPB | MASK_NO_UPDATE },
- {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
- {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
- | MASK_ISEL},
- {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
- | MASK_PPC_GFXOPT | MASK_ISEL},
- {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"970", PROCESSOR_POWER4,
- POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
- {"cell", PROCESSOR_CELL,
- POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
- {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS},
- {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
- {"G4", PROCESSOR_PPC7450, POWERPC_7400_MASK},
- {"G5", PROCESSOR_POWER4,
- POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
- {"titan", PROCESSOR_TITAN,
- POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
- {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
- {"power2", PROCESSOR_POWER,
- MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
- {"power3", PROCESSOR_PPC630,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
- {"power4", PROCESSOR_POWER4,
- POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
- | MASK_MFCRF},
- {"power5", PROCESSOR_POWER5,
- POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
- | MASK_MFCRF | MASK_POPCNTB},
- {"power5+", PROCESSOR_POWER5,
- POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
- | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
- {"power6", PROCESSOR_POWER6,
- POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
- | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
- | MASK_RECIP_PRECISION},
- {"power6x", PROCESSOR_POWER6,
- POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
- | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
- | MASK_MFPGPR | MASK_RECIP_PRECISION},
- {"power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */
- POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
- | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
- | MASK_VSX | MASK_RECIP_PRECISION},
- {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
- {"powerpc64", PROCESSOR_POWERPC64,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
- {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
- {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
- {"rios2", PROCESSOR_RIOS2,
- MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
- {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
- {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
- {"rs64", PROCESSOR_RS64A,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
- };
-
- const size_t ptt_size = ARRAY_SIZE (processor_target_table);
-
- /* Some OSs don't support saving the high part of 64-bit registers on
- context switch. Other OSs don't support saving Altivec registers.
- On those OSs, we don't touch the MASK_POWERPC64 or MASK_ALTIVEC
- settings; if the user wants either, the user must explicitly specify
- them and we won't interfere with the user's specification. */
-
- enum {
- POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
- POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
- | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
- | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
- | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
- | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE
- | MASK_RECIP_PRECISION)
- };
-
- /* Masks for instructions set at various powerpc ISAs. */
- enum {
- ISA_2_1_MASKS = MASK_MFCRF,
- ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB),
- ISA_2_4_MASKS = (ISA_2_2_MASKS | MASK_FPRND),
-
- /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't
- add ALTIVEC, since in general it isn't a win on power6. In ISA 2.04,
- fsel, fre, fsqrt, etc. were no longer documented as optional. Group
- masks by server and embedded. */
- ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION
- | MASK_PPC_GFXOPT | MASK_PPC_GPOPT),
- ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP),
-
- /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
- altivec is a win so enable it. */
- ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD),
- ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC
- | MASK_VSX)
- };
+ int cpu_index;
+ int tune_index;
+ struct cl_target_option *main_target_opt
+ = ((global_init_p || target_option_default_node == NULL)
+ ? NULL : TREE_TARGET_OPTION (target_option_default_node));
/* Numerous experiment shows that IRA based loop pressure
calculation works better for RTL loop invariant motion on targets
with enough (>= 32) registers. It is an expensive optimization.
So it is on only for peak performance. */
- if (optimize >= 3)
+ if (optimize >= 3 && global_init_p)
flag_ira_loop_pressure = 1;
/* Set the pointer size. */
@@ -2629,34 +2691,43 @@ rs6000_option_override_internal (const char *default_cpu)
set_masks &= ~target_flags_explicit;
/* Identify the processor type. */
- rs6000_select[0].string = default_cpu;
- rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
-
- for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
- {
- ptr = &rs6000_select[i];
- if (ptr->string != (char *)0 && ptr->string[0] != '\0')
- {
- for (j = 0; j < ptt_size; j++)
- if (! strcmp (ptr->string, processor_target_table[j].name))
- {
- if (ptr->set_tune_p)
- rs6000_cpu = processor_target_table[j].processor;
+ if (!default_cpu)
+ {
+ if (TARGET_POWERPC64)
+ default_cpu = "powerpc64";
+ else if (TARGET_POWERPC)
+ default_cpu = "powerpc";
+ }
+
+ /* Process the -mcpu=<xxx> and -mtune=<xxx> argument. If the user changed
+ the cpu in a target attribute or pragma, but did not specify a tuning
+ option, use the cpu for the tuning option rather than the option specified
+ with -mtune on the command line. */
+ if (rs6000_cpu_index > 0)
+ cpu_index = rs6000_cpu_index;
+ else if (main_target_opt != NULL && main_target_opt->x_rs6000_cpu_index > 0)
+ rs6000_cpu_index = cpu_index = main_target_opt->x_rs6000_cpu_index;
+ else
+ rs6000_cpu_index = cpu_index = rs6000_cpu_name_lookup (default_cpu);
- if (ptr->set_arch_p)
- {
- target_flags &= ~set_masks;
- target_flags |= (processor_target_table[j].target_enable
- & set_masks);
- }
- break;
- }
+ if (rs6000_tune_index > 0)
+ tune_index = rs6000_tune_index;
+ else
+ rs6000_tune_index = tune_index = cpu_index;
- if (j == ptt_size)
- error ("bad value (%s) for %s switch", ptr->string, ptr->name);
- }
+ if (cpu_index >= 0)
+ {
+ target_flags &= ~set_masks;
+ target_flags |= (processor_target_table[cpu_index].target_enable
+ & set_masks);
}
+ rs6000_cpu = ((tune_index >= 0)
+ ? processor_target_table[tune_index].processor
+ : (TARGET_POWERPC64
+ ? PROCESSOR_DEFAULT64
+ : PROCESSOR_DEFAULT));
+
if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
|| rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
{
@@ -2767,25 +2838,8 @@ rs6000_option_override_internal (const char *default_cpu)
if (rs6000_block_move_inline_limit < (TARGET_POWERPC64 ? 64 : 32))
rs6000_block_move_inline_limit = (TARGET_POWERPC64 ? 64 : 32);
- /* Set debug flags */
- if (rs6000_debug_name)
- {
- if (! strcmp (rs6000_debug_name, "all"))
- rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
- = rs6000_debug_addr = rs6000_debug_cost = 1;
- else if (! strcmp (rs6000_debug_name, "stack"))
- rs6000_debug_stack = 1;
- else if (! strcmp (rs6000_debug_name, "arg"))
- rs6000_debug_arg = 1;
- else if (! strcmp (rs6000_debug_name, "reg"))
- rs6000_debug_reg = 1;
- else if (! strcmp (rs6000_debug_name, "addr"))
- rs6000_debug_addr = 1;
- else if (! strcmp (rs6000_debug_name, "cost"))
- rs6000_debug_cost = 1;
- else
- error ("unknown -mdebug-%s switch", rs6000_debug_name);
-
+ if (global_init_p)
+ {
/* If the appropriate debug option is enabled, replace the target hooks
with debug versions that call the real version and then prints
debugging information. */
@@ -2813,41 +2867,50 @@ rs6000_option_override_internal (const char *default_cpu)
rs6000_mode_dependent_address_ptr
= rs6000_debug_mode_dependent_address;
}
- }
- if (rs6000_traceback_name)
- {
- if (! strncmp (rs6000_traceback_name, "full", 4))
- rs6000_traceback = traceback_full;
- else if (! strncmp (rs6000_traceback_name, "part", 4))
- rs6000_traceback = traceback_part;
- else if (! strncmp (rs6000_traceback_name, "no", 2))
- rs6000_traceback = traceback_none;
- else
- error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>",
- rs6000_traceback_name);
+ if (rs6000_veclibabi_name)
+ {
+ if (strcmp (rs6000_veclibabi_name, "mass") == 0)
+ rs6000_veclib_handler = rs6000_builtin_vectorized_libmass;
+ else
+ {
+ error ("unknown vectorization library ABI type (%s) for "
+ "-mveclibabi= switch", rs6000_veclibabi_name);
+ ret = false;
+ }
+ }
}
- if (rs6000_veclibabi_name)
+ if (!rs6000_explicit_options.long_double)
{
- if (strcmp (rs6000_veclibabi_name, "mass") == 0)
- rs6000_veclib_handler = rs6000_builtin_vectorized_libmass;
+ if (main_target_opt != NULL
+ && (main_target_opt->x_rs6000_long_double_type_size
+ != RS6000_DEFAULT_LONG_DOUBLE_SIZE))
+ error ("target attribute or pragma changes long double size");
else
- error ("unknown vectorization library ABI type (%s) for "
- "-mveclibabi= switch", rs6000_veclibabi_name);
+ rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
}
- if (!rs6000_explicit_options.long_double)
- rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
-
#ifndef POWERPC_LINUX
if (!rs6000_explicit_options.ieee)
rs6000_ieeequad = 1;
#endif
+ /* Disable VSX and Altivec silently if the user switched cpus to power7 in a
+ target attribute or pragma which automatically enables both options,
+ unless the altivec ABI was set. This is set by default for 64-bit, but
+ not for 32-bit. */
+ if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
+ target_flags &= ~((MASK_VSX | MASK_ALTIVEC) & ~target_flags_explicit);
+
/* Enable Altivec ABI for AIX -maltivec. */
if (TARGET_XCOFF && (TARGET_ALTIVEC || TARGET_VSX))
- rs6000_altivec_abi = 1;
+ {
+ if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
+ error ("target attribute or pragma changes AltiVec ABI");
+ else
+ rs6000_altivec_abi = 1;
+ }
/* The AltiVec ABI is the default for PowerPC-64 GNU/Linux. For
PowerPC-32 GNU/Linux, -maltivec implies the AltiVec ABI. It can
@@ -2856,7 +2919,13 @@ rs6000_option_override_internal (const char *default_cpu)
{
if (!rs6000_explicit_options.altivec_abi
&& (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX))
- rs6000_altivec_abi = 1;
+ {
+ if (main_target_opt != NULL &&
+ !main_target_opt->x_rs6000_altivec_abi)
+ error ("target attribute or pragma changes AltiVec ABI");
+ else
+ rs6000_altivec_abi = 1;
+ }
/* Enable VRSAVE for AltiVec ABI, unless explicitly overridden. */
if (!rs6000_explicit_options.vrsave)
@@ -2869,9 +2938,14 @@ rs6000_option_override_internal (const char *default_cpu)
&& DEFAULT_ABI == ABI_DARWIN
&& TARGET_64BIT)
{
- rs6000_darwin64_abi = 1;
- /* Default to natural alignment, for better performance. */
- rs6000_alignment_flags = MASK_ALIGN_NATURAL;
+ if (main_target_opt != NULL && !main_target_opt->x_rs6000_darwin64_abi)
+ error ("target attribute or pragma changes darwin64 ABI");
+ else
+ {
+ rs6000_darwin64_abi = 1;
+ /* Default to natural alignment, for better performance. */
+ rs6000_alignment_flags = MASK_ALIGN_NATURAL;
+ }
}
/* Place FP constants in the constant pool instead of TOC
@@ -2879,9 +2953,6 @@ rs6000_option_override_internal (const char *default_cpu)
if (flag_section_anchors)
TARGET_NO_FP_IN_TOC = 1;
- /* Handle -mtls-size option. */
- rs6000_parse_tls_size_option ();
-
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
@@ -2905,12 +2976,20 @@ rs6000_option_override_internal (const char *default_cpu)
/* For the powerpc-eabispe configuration, we set all these by
default, so let's unset them if we manually set another
CPU that is not the E500. */
- if (!rs6000_explicit_options.spe_abi)
- rs6000_spe_abi = 0;
- if (!rs6000_explicit_options.spe)
- rs6000_spe = 0;
- if (!rs6000_explicit_options.float_gprs)
- rs6000_float_gprs = 0;
+ if (main_target_opt != NULL
+ && ((main_target_opt->x_rs6000_spe_abi != rs6000_spe_abi)
+ || (main_target_opt->x_rs6000_spe != rs6000_spe)
+ || (main_target_opt->x_rs6000_float_gprs != rs6000_float_gprs)))
+ error ("target attribute or pragma changes SPE ABI");
+ else
+ {
+ if (!rs6000_explicit_options.spe_abi)
+ rs6000_spe_abi = 0;
+ if (!rs6000_explicit_options.spe)
+ rs6000_spe = 0;
+ if (!rs6000_explicit_options.float_gprs)
+ rs6000_float_gprs = 0;
+ }
if (!(target_flags_explicit & MASK_ISEL))
target_flags &= ~MASK_ISEL;
}
@@ -2983,79 +3062,83 @@ rs6000_option_override_internal (const char *default_cpu)
atoi (rs6000_sched_insert_nops_str));
}
+ if (global_init_p)
+ {
#ifdef TARGET_REGNAMES
- /* If the user desires alternate register names, copy in the
- alternate names now. */
- if (TARGET_REGNAMES)
- memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
+ /* If the user desires alternate register names, copy in the
+ alternate names now. */
+ if (TARGET_REGNAMES)
+ memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
#endif
- /* Set aix_struct_return last, after the ABI is determined.
- If -maix-struct-return or -msvr4-struct-return was explicitly
- used, don't override with the ABI default. */
- if (!rs6000_explicit_options.aix_struct_ret)
- aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
+ /* Set aix_struct_return last, after the ABI is determined.
+ If -maix-struct-return or -msvr4-struct-return was explicitly
+ used, don't override with the ABI default. */
+ if (!rs6000_explicit_options.aix_struct_ret)
+ aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
#if 0
- /* IBM XL compiler defaults to unsigned bitfields. */
- if (TARGET_XL_COMPAT)
- flag_signed_bitfields = 0;
+ /* IBM XL compiler defaults to unsigned bitfields. */
+ if (TARGET_XL_COMPAT)
+ flag_signed_bitfields = 0;
#endif
- if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
- REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
-
- if (TARGET_TOC)
- ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
+ if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
- /* We can only guarantee the availability of DI pseudo-ops when
- assembling for 64-bit targets. */
- if (!TARGET_64BIT)
- {
- targetm.asm_out.aligned_op.di = NULL;
- targetm.asm_out.unaligned_op.di = NULL;
- }
+ if (TARGET_TOC)
+ ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
- /* Set branch target alignment, if not optimizing for size. */
- if (!optimize_size)
- {
- /* Cell wants to be aligned 8byte for dual issue. Titan wants to be
- aligned 8byte to avoid misprediction by the branch predictor. */
- if (rs6000_cpu == PROCESSOR_TITAN
- || rs6000_cpu == PROCESSOR_CELL)
+ /* We can only guarantee the availability of DI pseudo-ops when
+ assembling for 64-bit targets. */
+ if (!TARGET_64BIT)
{
- if (align_functions <= 0)
- align_functions = 8;
- if (align_jumps <= 0)
- align_jumps = 8;
- if (align_loops <= 0)
- align_loops = 8;
- }
- if (rs6000_align_branch_targets)
+ targetm.asm_out.aligned_op.di = NULL;
+ targetm.asm_out.unaligned_op.di = NULL;
+ }
+
+
+ /* Set branch target alignment, if not optimizing for size. */
+ if (!optimize_size)
{
- if (align_functions <= 0)
- align_functions = 16;
- if (align_jumps <= 0)
- align_jumps = 16;
- if (align_loops <= 0)
+ /* Cell wants to be aligned 8byte for dual issue. Titan wants to be
+ aligned 8byte to avoid misprediction by the branch predictor. */
+ if (rs6000_cpu == PROCESSOR_TITAN
+ || rs6000_cpu == PROCESSOR_CELL)
{
- can_override_loop_align = 1;
- align_loops = 16;
+ if (align_functions <= 0)
+ align_functions = 8;
+ if (align_jumps <= 0)
+ align_jumps = 8;
+ if (align_loops <= 0)
+ align_loops = 8;
}
+ if (rs6000_align_branch_targets)
+ {
+ if (align_functions <= 0)
+ align_functions = 16;
+ if (align_jumps <= 0)
+ align_jumps = 16;
+ if (align_loops <= 0)
+ {
+ can_override_loop_align = 1;
+ align_loops = 16;
+ }
+ }
+ if (align_jumps_max_skip <= 0)
+ align_jumps_max_skip = 15;
+ if (align_loops_max_skip <= 0)
+ align_loops_max_skip = 15;
}
- if (align_jumps_max_skip <= 0)
- align_jumps_max_skip = 15;
- if (align_loops_max_skip <= 0)
- align_loops_max_skip = 15;
- }
- /* Arrange to save and restore machine status around nested functions. */
- init_machine_status = rs6000_init_machine_status;
+ /* Arrange to save and restore machine status around nested functions. */
+ init_machine_status = rs6000_init_machine_status;
- /* We should always be splitting complex arguments, but we can't break
- Linux and Darwin ABIs at the moment. For now, only AIX is fixed. */
- if (DEFAULT_ABI != ABI_AIX)
- targetm.calls.split_complex_arg = NULL;
+ /* We should always be splitting complex arguments, but we can't break
+ Linux and Darwin ABIs at the moment. For now, only AIX is fixed. */
+ if (DEFAULT_ABI != ABI_AIX)
+ targetm.calls.split_complex_arg = NULL;
+ }
/* Initialize rs6000_cost with the appropriate target costs. */
if (optimize_size)
@@ -3174,25 +3257,29 @@ rs6000_option_override_internal (const char *default_cpu)
gcc_unreachable ();
}
- maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
- rs6000_cost->simultaneous_prefetches,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_L1_CACHE_SIZE, rs6000_cost->l1_cache_size,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
- rs6000_cost->cache_line_size,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_L2_CACHE_SIZE, rs6000_cost->l2_cache_size,
- global_options.x_param_values,
- global_options_set.x_param_values);
-
- /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0)
- can be optimized to ap = __builtin_next_arg (0). */
- if (DEFAULT_ABI != ABI_V4)
- targetm.expand_builtin_va_start = NULL;
+ if (global_init_p)
+ {
+ maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
+ rs6000_cost->simultaneous_prefetches,
+ global_options.x_param_values,
+ global_options_set.x_param_values);
+ maybe_set_param_value (PARAM_L1_CACHE_SIZE, rs6000_cost->l1_cache_size,
+ global_options.x_param_values,
+ global_options_set.x_param_values);
+ maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
+ rs6000_cost->cache_line_size,
+ global_options.x_param_values,
+ global_options_set.x_param_values);
+ maybe_set_param_value (PARAM_L2_CACHE_SIZE, rs6000_cost->l2_cache_size,
+ global_options.x_param_values,
+ global_options_set.x_param_values);
+
+ /* If using typedef char *va_list, signal that
+ __builtin_va_start (&ap, 0) can be optimized to
+ ap = __builtin_next_arg (0). */
+ if (DEFAULT_ABI != ABI_V4)
+ targetm.expand_builtin_va_start = NULL;
+ }
/* Set up single/double float flags.
If TARGET_HARD_FLOAT is set, but neither single or double is set,
@@ -3211,6 +3298,16 @@ rs6000_option_override_internal (const char *default_cpu)
rs6000_single_float = rs6000_double_float = 1;
}
+ if (main_target_opt)
+ {
+ if (main_target_opt->x_rs6000_single_float != rs6000_single_float)
+ error ("target attribute or pragma changes single precision floating "
+ "point");
+ if (main_target_opt->x_rs6000_double_float != rs6000_double_float)
+ error ("target attribute or pragma changes double precision floating "
+ "point");
+ }
+
/* If not explicitly specified via option, decide whether to generate indexed
load/store instructions. */
if (TARGET_AVOID_XFORM == -1)
@@ -3254,6 +3351,7 @@ rs6000_option_override_internal (const char *default_cpu)
error ("unknown option for -mrecip=%s", q);
invert = false;
mask = 0;
+ ret = false;
}
}
@@ -3264,7 +3362,14 @@ rs6000_option_override_internal (const char *default_cpu)
}
}
- rs6000_init_hard_regno_mode_ok ();
+ rs6000_init_hard_regno_mode_ok (global_init_p);
+
+ /* Save the initial options in case the user does function specific options */
+ if (global_init_p)
+ target_option_default_node = target_option_current_node
+ = build_target_option_node ();
+
+ return ret;
}
/* Implement TARGET_OPTION_OVERRIDE. On the RS/6000 this is used to
@@ -3273,9 +3378,10 @@ rs6000_option_override_internal (const char *default_cpu)
static void
rs6000_option_override (void)
{
- rs6000_option_override_internal (OPTION_TARGET_CPU_DEFAULT);
+ (void) rs6000_option_override_internal (true);
}
+
/* Implement targetm.vectorize.builtin_mask_for_load. */
static tree
rs6000_builtin_mask_for_load (void)
@@ -3712,23 +3818,6 @@ rs6000_parse_yes_no_option (const char *name, const char *value, int *flag)
error ("unknown -m%s= option specified: '%s'", name, value);
}
-/* Validate and record the size specified with the -mtls-size option. */
-
-static void
-rs6000_parse_tls_size_option (void)
-{
- if (rs6000_tls_size_string == 0)
- return;
- else if (strcmp (rs6000_tls_size_string, "16") == 0)
- rs6000_tls_size = 16;
- else if (strcmp (rs6000_tls_size_string, "32") == 0)
- rs6000_tls_size = 32;
- else if (strcmp (rs6000_tls_size_string, "64") == 0)
- rs6000_tls_size = 64;
- else
- error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string);
-}
-
/* Implement TARGET_OPTION_INIT_STRUCT. */
static void
@@ -4101,6 +4190,7 @@ rs6000_handle_option (size_t code, const char *arg, int value)
{
enum fpu_type_t fpu_type = FPU_NONE;
int isel;
+ char *p, *q;
switch (code)
{
@@ -4140,11 +4230,11 @@ rs6000_handle_option (size_t code, const char *arg, int value)
#if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
case OPT_mcmodel_:
if (strcmp (arg, "small") == 0)
- cmodel = CMODEL_SMALL;
+ rs6000_current_cmodel = CMODEL_SMALL;
else if (strcmp (arg, "medium") == 0)
- cmodel = CMODEL_MEDIUM;
+ rs6000_current_cmodel = CMODEL_MEDIUM;
else if (strcmp (arg, "large") == 0)
- cmodel = CMODEL_LARGE;
+ rs6000_current_cmodel = CMODEL_LARGE;
else
{
error ("invalid option for -mcmodel: '%s'", arg);
@@ -4245,7 +4335,45 @@ rs6000_handle_option (size_t code, const char *arg, int value)
break;
case OPT_mdebug_:
- rs6000_debug_name = arg;
+ p = ASTRDUP (arg);
+ rs6000_debug = 0;
+
+ while ((q = strtok (p, ",")) != NULL)
+ {
+ unsigned mask = 0;
+ bool invert;
+
+ p = NULL;
+ if (*q == '!')
+ {
+ invert = true;
+ q++;
+ }
+ else
+ invert = false;
+
+ if (! strcmp (q, "all"))
+ mask = MASK_DEBUG_ALL;
+ else if (! strcmp (q, "stack"))
+ mask = MASK_DEBUG_STACK;
+ else if (! strcmp (q, "arg"))
+ mask = MASK_DEBUG_ARG;
+ else if (! strcmp (q, "reg"))
+ mask = MASK_DEBUG_REG;
+ else if (! strcmp (q, "addr"))
+ mask = MASK_DEBUG_ADDR;
+ else if (! strcmp (q, "cost"))
+ mask = MASK_DEBUG_COST;
+ else if (! strcmp (q, "target"))
+ mask = MASK_DEBUG_TARGET;
+ else
+ error ("unknown -mdebug-%s switch", q);
+
+ if (invert)
+ rs6000_debug &= ~mask;
+ else
+ rs6000_debug |= mask;
+ }
break;
#ifdef TARGET_USES_SYSV4_OPT
@@ -4258,7 +4386,14 @@ rs6000_handle_option (size_t code, const char *arg, int value)
break;
case OPT_mtls_size_:
- rs6000_tls_size_string = arg;
+ if (strcmp (arg, "16") == 0)
+ rs6000_tls_size = 16;
+ else if (strcmp (arg, "32") == 0)
+ rs6000_tls_size = 32;
+ else if (strcmp (arg, "64") == 0)
+ rs6000_tls_size = 64;
+ else
+ error ("bad value %qs for -mtls-size switch", arg);
break;
case OPT_mrelocatable:
@@ -4348,14 +4483,28 @@ rs6000_handle_option (size_t code, const char *arg, int value)
case OPT_mcpu_:
rs6000_select[1].string = arg;
+ rs6000_cpu_index = rs6000_cpu_name_lookup (arg);
+ if (rs6000_cpu_index < 0)
+ error ("bad value (%s) for -mcpu", arg);
break;
case OPT_mtune_:
rs6000_select[2].string = arg;
+ rs6000_tune_index = rs6000_cpu_name_lookup (arg);
+ if (rs6000_tune_index < 0)
+ error ("bad value (%s) for -mtune", arg);
break;
case OPT_mtraceback_:
- rs6000_traceback_name = arg;
+ if (! strncmp (arg, "full", 4))
+ rs6000_traceback = traceback_full;
+ else if (! strncmp (arg, "part", 4))
+ rs6000_traceback = traceback_part;
+ else if (! strncmp (arg, "no", 2))
+ rs6000_traceback = traceback_none;
+ else
+ error ("unknown -mtraceback arg %qs; expecting %<full%>, "
+ "%<partial%> or %<none%>", arg);
break;
case OPT_mfloat_gprs_:
@@ -6845,6 +6994,9 @@ rs6000_conditional_register_usage (void)
{
int i;
+ if (TARGET_DEBUG_TARGET)
+ fprintf (stderr, "rs6000_conditional_register_usage called\n");
+
/* Set MQ register fixed (already call_used) if not POWER
architecture (RIOS1, RIOS2, RSC, and PPC601) so that it will not
be allocated. */
@@ -27145,6 +27297,585 @@ rs6000_final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
}
+/* Mask options that we want to support inside of attribute((target)) and
+ #pragma GCC target operations. Note, we do not include things like
+ 64/32-bit, endianess, hard/soft floating point, etc. that would have
+ different calling sequences. */
+
+struct rs6000_opt_mask {
+ const char *name; /* option name */
+ int mask; /* mask to set */
+ bool invert; /* invert sense of mask */
+ bool valid_target; /* option is a target option */
+};
+
+static struct rs6000_opt_mask const rs6000_opt_masks[] =
+{
+ { "altivec", MASK_ALTIVEC, false, true },
+ { "cmpb", MASK_CMPB, false, true },
+ { "dlmzb", MASK_DLMZB, false, true },
+ { "fprnd", MASK_FPRND, false, true },
+ { "hard-dfp", MASK_DFP, false, true },
+ { "isel", MASK_ISEL, false, true },
+ { "mfcrf", MASK_MFCRF, false, true },
+ { "mfpgpr", MASK_MFPGPR, false, true },
+ { "mulhw", MASK_MULHW, false, true },
+ { "multiple", MASK_MULTIPLE, false, true },
+ { "update", MASK_NO_UPDATE, true , true },
+ { "popcntb", MASK_POPCNTB, false, true },
+ { "popcntd", MASK_POPCNTD, false, true },
+ { "powerpc-gfxopt", MASK_PPC_GFXOPT, false, true },
+ { "powerpc-gpopt", MASK_PPC_GPOPT, false, true },
+ { "recip-precision", MASK_RECIP_PRECISION, false, true },
+ { "string", MASK_STRING, false, true },
+ { "vsx", MASK_VSX, false, true },
+#ifdef MASK_64BIT
+#if TARGET_AIX_OS
+ { "aix64", MASK_64BIT, false, false },
+ { "aix32", MASK_64BIT, true, false },
+#else
+ { "64", MASK_64BIT, false, false },
+ { "32", MASK_64BIT, true, false },
+#endif
+#endif
+#ifdef MASK_EABI
+ { "eabi", MASK_EABI, false, false },
+#endif
+#ifdef MASK_LITTLE_ENDIAN
+ { "little", MASK_LITTLE_ENDIAN, false, false },
+ { "big", MASK_LITTLE_ENDIAN, true, false },
+#endif
+#ifdef MASK_RELOCATABLE
+ { "relocatable", MASK_RELOCATABLE, false, false },
+#endif
+#ifdef MASK_STRICT_ALIGN
+ { "strict-align", MASK_STRICT_ALIGN, false, false },
+#endif
+ { "power", MASK_POWER, false, false },
+ { "power2", MASK_POWER2, false, false },
+ { "powerpc", MASK_POWERPC, false, false },
+ { "soft-float", MASK_SOFT_FLOAT, false, false },
+ { "string", MASK_STRING, false, false },
+};
+
+/* Option variables that we want to support inside attribute((target)) and
+ #pragma GCC target operations. */
+
+struct rs6000_opt_var {
+ const char *name; /* option name */
+ size_t global_offset; /* offset of the option in global_options. */
+ size_t target_offset; /* offset of the option in target optiosn. */
+};
+
+static struct rs6000_opt_var const rs6000_opt_vars[] =
+{
+ { "friz",
+ offsetof (struct gcc_options, x_TARGET_FRIZ),
+ offsetof (struct cl_target_option, x_TARGET_FRIZ), },
+ { "avoid-indexed-addresses",
+ offsetof (struct gcc_options, x_TARGET_AVOID_XFORM),
+ offsetof (struct cl_target_option, x_TARGET_AVOID_XFORM) },
+ { "paired",
+ offsetof (struct gcc_options, x_rs6000_paired_float),
+ offsetof (struct cl_target_option, x_rs6000_paired_float), },
+ { "longcall",
+ offsetof (struct gcc_options, x_rs6000_default_long_calls),
+ offsetof (struct cl_target_option, x_rs6000_default_long_calls), },
+};
+
+/* Inner function to handle attribute((target("..."))) and #pragma GCC target
+ parsing. Return true if there were no errors. */
+
+static bool
+rs6000_inner_target_options (tree args, bool attr_p)
+{
+ bool ret = true;
+
+ if (args == NULL_TREE)
+ ;
+
+ else if (TREE_CODE (args) == STRING_CST)
+ {
+ char *p = ASTRDUP (TREE_STRING_POINTER (args));
+ char *q;
+
+ while ((q = strtok (p, ",")) != NULL)
+ {
+ bool error_p = false;
+ bool not_valid_p = false;
+ const char *cpu_opt = NULL;
+
+ p = NULL;
+ if (strncmp (q, "cpu=", 4) == 0)
+ {
+ int cpu_index = rs6000_cpu_name_lookup (q+4);
+ if (cpu_index >= 0)
+ rs6000_cpu_index = cpu_index;
+ else
+ {
+ error_p = true;
+ cpu_opt = q+4;
+ }
+ }
+ else if (strncmp (q, "tune=", 5) == 0)
+ {
+ int tune_index = rs6000_cpu_name_lookup (q+5);
+ if (tune_index >= 0)
+ rs6000_tune_index = tune_index;
+ else
+ {
+ error_p = true;
+ cpu_opt = q+5;
+ }
+ }
+ else
+ {
+ size_t i;
+ bool invert = false;
+ char *r = q;
+
+ error_p = true;
+ if (strncmp (r, "no-", 3) == 0)
+ {
+ invert = true;
+ r += 3;
+ }
+
+ for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
+ if (strcmp (r, rs6000_opt_masks[i].name) == 0)
+ {
+ int mask = rs6000_opt_masks[i].mask;
+
+ if (!rs6000_opt_masks[i].valid_target)
+ not_valid_p = true;
+ else
+ {
+ error_p = false;
+ target_flags_explicit |= mask;
+
+ if (rs6000_opt_masks[i].invert)
+ invert = !invert;
+
+ if (invert)
+ target_flags &= ~mask;
+ else
+ target_flags |= mask;
+ }
+ break;
+ }
+
+ if (error_p && !not_valid_p)
+ {
+ for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
+ if (strcmp (r, rs6000_opt_vars[i].name) == 0)
+ {
+ size_t j = rs6000_opt_vars[i].global_offset;
+ ((int *) &global_options)[j] = !invert;
+ error_p = false;
+ break;
+ }
+ }
+ }
+
+ if (error_p)
+ {
+ const char *eprefix, *esuffix;
+
+ ret = false;
+ if (attr_p)
+ {
+ eprefix = "__attribute__((__target__(";
+ esuffix = ")))";
+ }
+ else
+ {
+ eprefix = "#pragma GCC target ";
+ esuffix = "";
+ }
+
+ if (cpu_opt)
+ error ("invalid cpu \"%s\" for %s\"%s\"%s", cpu_opt, eprefix,
+ q, esuffix);
+ else if (not_valid_p)
+ error ("%s\"%s\"%s is not allowed", eprefix, q, esuffix);
+ else
+ error ("%s\"%s\"%s is invalid", eprefix, q, esuffix);
+ }
+ }
+ }
+
+ else if (TREE_CODE (args) == TREE_LIST)
+ {
+ do
+ {
+ tree value = TREE_VALUE (args);
+ if (value)
+ {
+ bool ret2 = rs6000_inner_target_options (value, attr_p);
+ if (!ret2)
+ ret = false;
+ }
+ args = TREE_CHAIN (args);
+ }
+ while (args != NULL_TREE);
+ }
+
+ else
+ gcc_unreachable ();
+
+ return ret;
+}
+
+/* Print out the target options as a list for -mdebug=target. */
+
+static void
+rs6000_debug_target_options (tree args, const char *prefix)
+{
+ if (args == NULL_TREE)
+ fprintf (stderr, "%s<NULL>", prefix);
+
+ else if (TREE_CODE (args) == STRING_CST)
+ {
+ char *p = ASTRDUP (TREE_STRING_POINTER (args));
+ char *q;
+
+ while ((q = strtok (p, ",")) != NULL)
+ {
+ p = NULL;
+ fprintf (stderr, "%s\"%s\"", prefix, q);
+ prefix = ", ";
+ }
+ }
+
+ else if (TREE_CODE (args) == TREE_LIST)
+ {
+ do
+ {
+ tree value = TREE_VALUE (args);
+ if (value)
+ {
+ rs6000_debug_target_options (value, prefix);
+ prefix = ", ";
+ }
+ args = TREE_CHAIN (args);
+ }
+ while (args != NULL_TREE);
+ }
+
+ else
+ gcc_unreachable ();
+
+ return;
+}
+
+
+/* Hook to validate attribute((target("..."))). */
+
+static bool
+rs6000_valid_attribute_p (tree fndecl,
+ tree ARG_UNUSED (name),
+ tree args,
+ int flags)
+{
+ struct cl_target_option cur_target;
+ bool ret;
+ tree old_optimize = build_optimization_node ();
+ tree new_target, new_optimize;
+ tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+ gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE));
+
+ if (TARGET_DEBUG_TARGET)
+ {
+ tree tname = DECL_NAME (fndecl);
+ fprintf (stderr, "\n==================== rs6000_valid_attribute_p:\n");
+ if (tname)
+ fprintf (stderr, "function: %.*s\n",
+ (int) IDENTIFIER_LENGTH (tname),
+ IDENTIFIER_POINTER (tname));
+ else
+ fprintf (stderr, "function: unknown\n");
+
+ fprintf (stderr, "args:");
+ rs6000_debug_target_options (args, " ");
+ fprintf (stderr, "\n");
+
+ if (flags)
+ fprintf (stderr, "flags: 0x%x\n", flags);
+
+ fprintf (stderr, "--------------------\n");
+ }
+
+ old_optimize = build_optimization_node ();
+ func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+ /* If the function changed the optimization levels as well as setting target
+ options, start with the optimizations specified. */
+ if (func_optimize && func_optimize != old_optimize)
+ cl_optimization_restore (&global_options,
+ TREE_OPTIMIZATION (func_optimize));
+
+ /* The target attributes may also change some optimization flags, so update
+ the optimization options if necessary. */
+ cl_target_option_save (&cur_target, &global_options);
+ rs6000_cpu_index = rs6000_tune_index = -1;
+ ret = rs6000_inner_target_options (args, true);
+
+ /* Set up any additional state. */
+ if (ret)
+ {
+ ret = rs6000_option_override_internal (false);
+ new_target = build_target_option_node ();
+ }
+ else
+ new_target = NULL;
+
+ new_optimize = build_optimization_node ();
+
+ if (!new_target)
+ ret = false;
+
+ else if (fndecl)
+ {
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
+
+ if (old_optimize != new_optimize)
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+ }
+
+ cl_target_option_restore (&global_options, &cur_target);
+
+ if (old_optimize != new_optimize)
+ cl_optimization_restore (&global_options,
+ TREE_OPTIMIZATION (old_optimize));
+
+ return ret;
+}
+
+
+/* Hook to validate the current #pragma GCC target and set the state, and
+ update the macros based on what was changed. If ARGS is NULL, then
+ POP_TARGET is used to reset the options. */
+
+bool
+rs6000_pragma_target_parse (tree args, tree pop_target)
+{
+ tree cur_tree;
+ bool ret;
+
+ if (TARGET_DEBUG_TARGET)
+ {
+ fprintf (stderr, "\n==================== rs6000_pragma_target_parse\n");
+ fprintf (stderr, "args:");
+ rs6000_debug_target_options (args, " ");
+ fprintf (stderr, "\n");
+
+ if (pop_target)
+ {
+ fprintf (stderr, "pop_target:\n");
+ debug_tree (pop_target);
+ }
+ else
+ fprintf (stderr, "pop_target: <NULL>\n");
+
+ fprintf (stderr, "--------------------\n");
+ }
+
+ if (! args)
+ {
+ ret = true;
+ cur_tree = ((pop_target)
+ ? pop_target
+ : target_option_default_node);
+ cl_target_option_restore (&global_options,
+ TREE_TARGET_OPTION (cur_tree));
+ }
+ else
+ {
+ rs6000_cpu_index = rs6000_tune_index = -1;
+ ret = rs6000_inner_target_options (args, false);
+ cur_tree = build_target_option_node ();
+
+ if (!cur_tree)
+ ret = false;
+ }
+
+ if (cur_tree)
+ target_option_current_node = cur_tree;
+
+ return ret;
+}
+
+
+/* Remember the last target of rs6000_set_current_function. */
+static GTY(()) tree rs6000_previous_fndecl;
+
+/* Establish appropriate back-end context for processing the function
+ FNDECL. The argument might be NULL to indicate processing at top
+ level, outside of any function scope. */
+static void
+rs6000_set_current_function (tree fndecl)
+{
+ tree old_tree = (rs6000_previous_fndecl
+ ? DECL_FUNCTION_SPECIFIC_TARGET (rs6000_previous_fndecl)
+ : NULL_TREE);
+
+ tree new_tree = (fndecl
+ ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
+ : NULL_TREE);
+
+ if (TARGET_DEBUG_TARGET)
+ {
+ bool print_final = false;
+ fprintf (stderr, "\n==================== rs6000_set_current_function");
+
+ if (fndecl)
+ fprintf (stderr, ", fndecl %s (%p)",
+ (DECL_NAME (fndecl)
+ ? IDENTIFIER_POINTER (DECL_NAME (fndecl))
+ : "<unknown>"), (void *)fndecl);
+
+ if (rs6000_previous_fndecl)
+ fprintf (stderr, ", prev_fndecl (%p)", (void *)rs6000_previous_fndecl);
+
+ fprintf (stderr, "\n");
+ if (new_tree)
+ {
+ fprintf (stderr, "\nnew fndecl target specific options:\n");
+ debug_tree (new_tree);
+ print_final = true;
+ }
+
+ if (old_tree)
+ {
+ fprintf (stderr, "\nold fndecl target specific options:\n");
+ debug_tree (old_tree);
+ print_final = true;
+ }
+
+ if (print_final)
+ fprintf (stderr, "--------------------\n");
+ }
+
+ /* Only change the context if the function changes. This hook is called
+ several times in the course of compiling a function, and we don't want to
+ slow things down too much or call target_reinit when it isn't safe. */
+ if (fndecl && fndecl != rs6000_previous_fndecl)
+ {
+ rs6000_previous_fndecl = fndecl;
+ if (old_tree == new_tree)
+ ;
+
+ else if (new_tree)
+ {
+ cl_target_option_restore (&global_options,
+ TREE_TARGET_OPTION (new_tree));
+ target_reinit ();
+ }
+
+ else if (old_tree)
+ {
+ struct cl_target_option *def
+ = TREE_TARGET_OPTION (target_option_current_node);
+
+ cl_target_option_restore (&global_options, def);
+ target_reinit ();
+ }
+ }
+}
+
+
+/* Save the current options */
+
+static void
+rs6000_function_specific_save (struct cl_target_option *ptr)
+{
+ ptr->rs6000_target_flags_explicit = target_flags_explicit;
+}
+
+/* Restore the current options */
+
+static void
+rs6000_function_specific_restore (struct cl_target_option *ptr)
+{
+ target_flags_explicit = ptr->rs6000_target_flags_explicit;
+ (void) rs6000_option_override_internal (false);
+}
+
+/* Print the current options */
+
+static void
+rs6000_function_specific_print (FILE *file, int indent,
+ struct cl_target_option *ptr)
+{
+ size_t i;
+ int flags = ptr->x_target_flags;
+
+ /* Print the various mask options. */
+ for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
+ if ((flags & rs6000_opt_masks[i].mask) != 0)
+ {
+ flags &= ~ rs6000_opt_masks[i].mask;
+ fprintf (file, "%*s-m%s%s\n", indent, "",
+ rs6000_opt_masks[i].invert ? "no-" : "",
+ rs6000_opt_masks[i].name);
+ }
+
+ /* Print the various options that are variables. */
+ for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
+ {
+ size_t j = rs6000_opt_vars[i].target_offset;
+ if (((signed char *) ptr)[j])
+ fprintf (file, "%*s-m%s\n", indent, "",
+ rs6000_opt_vars[i].name);
+ }
+}
+
+
+/* Hook to determine if one function can safely inline another. */
+
+static bool
+rs6000_can_inline_p (tree caller, tree callee)
+{
+ bool ret = false;
+ tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
+ tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
+
+ /* If callee has no option attributes, then it is ok to inline. */
+ if (!callee_tree)
+ ret = true;
+
+ /* If caller has no option attributes, but callee does then it is not ok to
+ inline. */
+ else if (!caller_tree)
+ ret = false;
+
+ else
+ {
+ struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
+ struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
+
+ /* Callee's options should a subset of the caller's, i.e. a vsx function
+ can inline an altivec function but a non-vsx function can't inline a
+ vsx function. */
+ if ((caller_opts->x_target_flags & callee_opts->x_target_flags)
+ == callee_opts->x_target_flags)
+ ret = true;
+ }
+
+ if (TARGET_DEBUG_TARGET)
+ fprintf (stderr, "rs6000_can_inline_p:, caller %s, callee %s, %s inline\n",
+ (DECL_NAME (caller)
+ ? IDENTIFIER_POINTER (DECL_NAME (caller))
+ : "<unknown>"),
+ (DECL_NAME (callee)
+ ? IDENTIFIER_POINTER (DECL_NAME (callee))
+ : "<unknown>"),
+ (ret ? "can" : "cannot"));
+
+ return ret;
+}
+
/* Allocate a stack temp and fixup the address so it meets the particular
memory requirements (either offetable or REG+REG addressing). */
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 9162e4f..7b4a27e 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -29,6 +29,10 @@
/* Note that some other tm.h files include this one and then override
many of the definitions. */
+#ifndef RS6000_OPTS_H
+#include "config/rs6000/rs6000-opts.h"
+#endif
+
/* Definitions for the object file format. These are set at
compile-time. */
@@ -299,16 +303,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define TARGET_SECURE_PLT 0
#endif
-/* Code model for 64-bit linux.
- small: 16-bit toc offsets.
- medium: 32-bit toc offsets, static data and code within 2G of TOC pointer.
- large: 32-bit toc offsets, no limit on static data and code. */
-enum rs6000_cmodel {
- CMODEL_SMALL,
- CMODEL_MEDIUM,
- CMODEL_LARGE
-};
-
#ifndef TARGET_CMODEL
#define TARGET_CMODEL CMODEL_SMALL
#endif
@@ -338,40 +332,6 @@ enum rs6000_cmodel {
#define TARGET_DEFAULT (MASK_POWER | MASK_MULTIPLE | MASK_STRING)
-/* Processor type. Order must match cpu attribute in MD file. */
-enum processor_type
- {
- PROCESSOR_RIOS1,
- PROCESSOR_RIOS2,
- PROCESSOR_RS64A,
- PROCESSOR_MPCCORE,
- PROCESSOR_PPC403,
- PROCESSOR_PPC405,
- PROCESSOR_PPC440,
- PROCESSOR_PPC476,
- PROCESSOR_PPC601,
- PROCESSOR_PPC603,
- PROCESSOR_PPC604,
- PROCESSOR_PPC604e,
- PROCESSOR_PPC620,
- PROCESSOR_PPC630,
- PROCESSOR_PPC750,
- PROCESSOR_PPC7400,
- PROCESSOR_PPC7450,
- PROCESSOR_PPC8540,
- PROCESSOR_PPCE300C2,
- PROCESSOR_PPCE300C3,
- PROCESSOR_PPCE500MC,
- PROCESSOR_PPCE500MC64,
- PROCESSOR_POWER4,
- PROCESSOR_POWER5,
- PROCESSOR_POWER6,
- PROCESSOR_POWER7,
- PROCESSOR_CELL,
- PROCESSOR_PPCA2,
- PROCESSOR_TITAN
-};
-
/* FPU operations supported.
Each use of TARGET_SINGLE_FLOAT or TARGET_DOUBLE_FLOAT must
also test TARGET_HARD_FLOAT. */
@@ -381,8 +341,6 @@ enum processor_type
#define TARGET_SIMPLE_FPU 0
#define TARGET_XILINX_FPU 0
-extern enum processor_type rs6000_cpu;
-
/* Recast the processor type to the cpu attribute. */
#define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu)
@@ -396,47 +354,12 @@ extern enum processor_type rs6000_cpu;
#define PROCESSOR_DEFAULT PROCESSOR_RIOS1
#define PROCESSOR_DEFAULT64 PROCESSOR_RS64A
-/* FP processor type. */
-enum fpu_type_t
-{
- FPU_NONE, /* No FPU */
- FPU_SF_LITE, /* Limited Single Precision FPU */
- FPU_DF_LITE, /* Limited Double Precision FPU */
- FPU_SF_FULL, /* Full Single Precision FPU */
- FPU_DF_FULL /* Full Double Single Precision FPU */
-};
-
extern enum fpu_type_t fpu_type;
/* Specify the dialect of assembler to use. New mnemonics is dialect one
and the old mnemonics are dialect zero. */
#define ASSEMBLER_DIALECT (TARGET_NEW_MNEMONICS ? 1 : 0)
-/* Types of costly dependences. */
-enum rs6000_dependence_cost
- {
- max_dep_latency = 1000,
- no_dep_costly,
- all_deps_costly,
- true_store_to_load_dep_costly,
- store_to_load_dep_costly
- };
-
-/* Types of nop insertion schemes in sched target hook sched_finish. */
-enum rs6000_nop_insertion
- {
- sched_finish_regroup_exact = 1000,
- sched_finish_pad_groups,
- sched_finish_none
- };
-
-/* Dispatch group termination caused by an insn. */
-enum group_termination
- {
- current_group,
- previous_group
- };
-
/* rs6000_select[0] is reserved for the default cpu defined via --with-cpu */
struct rs6000_cpu_select
{
@@ -449,42 +372,25 @@ struct rs6000_cpu_select
extern struct rs6000_cpu_select rs6000_select[];
/* Debug support */
-extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
-extern int rs6000_debug_stack; /* debug stack applications */
-extern int rs6000_debug_arg; /* debug argument handling */
-extern int rs6000_debug_reg; /* debug register handling */
-extern int rs6000_debug_addr; /* debug memory addressing */
-extern int rs6000_debug_cost; /* debug rtx_costs */
-
-#define TARGET_DEBUG_STACK rs6000_debug_stack
-#define TARGET_DEBUG_ARG rs6000_debug_arg
-#define TARGET_DEBUG_REG rs6000_debug_reg
-#define TARGET_DEBUG_ADDR rs6000_debug_addr
-#define TARGET_DEBUG_COST rs6000_debug_cost
-
-extern const char *rs6000_traceback_name; /* Type of traceback table. */
-
-/* These are separate from target_flags because we've run out of bits
- there. */
-extern int rs6000_long_double_type_size;
-extern int rs6000_ieeequad;
-extern int rs6000_altivec_abi;
-extern int rs6000_spe_abi;
-extern int rs6000_spe;
-extern int rs6000_float_gprs;
-extern int rs6000_alignment_flags;
-extern const char *rs6000_sched_insert_nops_str;
-extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
-
-/* Describe which vector unit to use for a given machine mode. */
-enum rs6000_vector {
- VECTOR_NONE, /* Type is not a vector or not supported */
- VECTOR_ALTIVEC, /* Use altivec for vector processing */
- VECTOR_VSX, /* Use VSX for vector processing */
- VECTOR_PAIRED, /* Use paired floating point for vectors */
- VECTOR_SPE, /* Use SPE for vector processing */
- VECTOR_OTHER /* Some other vector unit */
-};
+#define MASK_DEBUG_STACK 0x01 /* debug stack applications */
+#define MASK_DEBUG_ARG 0x02 /* debug argument handling */
+#define MASK_DEBUG_REG 0x04 /* debug register handling */
+#define MASK_DEBUG_ADDR 0x08 /* debug memory addressing */
+#define MASK_DEBUG_COST 0x10 /* debug rtx codes */
+#define MASK_DEBUG_TARGET 0x20 /* debug target attribute/pragma */
+#define MASK_DEBUG_ALL (MASK_DEBUG_STACK \
+ | MASK_DEBUG_ARG \
+ | MASK_DEBUG_REG \
+ | MASK_DEBUG_ADDR \
+ | MASK_DEBUG_COST \
+ | MASK_DEBUG_TARGET)
+
+#define TARGET_DEBUG_STACK (rs6000_debug & MASK_DEBUG_STACK)
+#define TARGET_DEBUG_ARG (rs6000_debug & MASK_DEBUG_ARG)
+#define TARGET_DEBUG_REG (rs6000_debug & MASK_DEBUG_REG)
+#define TARGET_DEBUG_ADDR (rs6000_debug & MASK_DEBUG_ADDR)
+#define TARGET_DEBUG_COST (rs6000_debug & MASK_DEBUG_COST)
+#define TARGET_DEBUG_TARGET (rs6000_debug & MASK_DEBUG_TARGET)
extern enum rs6000_vector rs6000_vector_unit[];
@@ -628,6 +534,7 @@ extern unsigned char rs6000_recip_bits[];
/* Target pragma. */
#define REGISTER_TARGET_PRAGMAS() do { \
c_register_pragma (0, "longcall", rs6000_pragma_longcall); \
+ targetm.target_option.pragma_parse = rs6000_pragma_target_parse; \
targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \
} while (0)
@@ -1465,16 +1372,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
/* Stack layout; function entry, exit and calling. */
-/* Enumeration to give which calling sequence to use. */
-enum rs6000_abi {
- ABI_NONE,
- ABI_AIX, /* IBM's AIX */
- ABI_V4, /* System V.4/eabi */
- ABI_DARWIN /* Apple's Darwin (OS X kernel) */
-};
-
-extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
-
/* Define this if pushing a word on the stack
makes the stack pointer a smaller address. */
#define STACK_GROWS_DOWNWARD
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 063036a..2c6a861 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -20,6 +20,109 @@
; along with GCC; see the file COPYING3. If not see
; <http://www.gnu.org/licenses/>.
+HeaderInclude
+config/rs6000/rs6000-opts.h
+
+;; Current processor
+TargetVariable
+enum processor_type rs6000_cpu = PROCESSOR_RIOS1
+
+;; Always emit branch hint bits.
+TargetVariable
+unsigned char rs6000_always_hint
+
+;; Schedule instructions for group formation.
+TargetVariable
+unsigned char rs6000_sched_groups
+
+;; Align branch targets.
+TargetVariable
+unsigned char rs6000_align_branch_targets
+
+;; Support for -msched-costly-dep option.
+TargetVariable
+enum rs6000_dependence_cost rs6000_sched_costly_dep = no_dep_costly
+
+;; Support for -minsert-sched-nops option.
+TargetVariable
+enum rs6000_nop_insertion rs6000_sched_insert_nops = sched_finish_none
+
+;; Size of long double.
+TargetVariable
+unsigned char rs6000_long_double_type_size
+
+;; IEEE quad extended precision long double.
+TargetVariable
+unsigned char rs6000_ieeequad
+
+;; Nonzero to use AltiVec ABI.
+TargetVariable
+unsigned char rs6000_altivec_abi
+
+;; Nonzero if we want SPE SIMD instructions.
+TargetVariable
+int rs6000_spe
+
+;; Nonzero if we want SPE ABI extensions.
+TargetVariable
+unsigned char rs6000_spe_abi
+
+;; Nonzero if floating point operations are done in the GPRs.
+TargetVariable
+unsigned char rs6000_float_gprs
+
+;; Nonzero if we want Darwin's struct-by-value-in-regs ABI.
+TargetVariable
+unsigned char rs6000_darwin64_abi
+
+;; Non-zero to allow overriding loop alignment.
+TargetVariable
+unsigned char can_override_loop_align
+
+;; Which small data model to use (for System V targets only)
+TargetVariable
+enum rs6000_sdata_type rs6000_sdata = SDATA_DATA
+
+;; Bit size of immediate TLS offsets and string from which it is decoded.
+TargetVariable
+int rs6000_tls_size = 32
+
+;; ABI enumeration available for subtarget to use.
+TargetVariable
+enum rs6000_abi rs6000_current_abi = ABI_NONE
+
+;; Type of traceback to use.
+TargetVariable
+enum rs6000_traceback_type rs6000_traceback = traceback_default
+
+;; Control alignment for fields within structures.
+TargetVariable
+unsigned char rs6000_alignment_flags
+
+;; Code model for 64-bit linux.
+TargetVariable
+enum rs6000_cmodel rs6000_current_cmodel = CMODEL_SMALL
+
+;; What type of reciprocal estimation instructions to generate
+TargetVariable
+unsigned int rs6000_recip_control
+
+;; -mcpu=<xxx> as an index into the processor_target_table or -1
+TargetVariable
+int rs6000_cpu_index = -1
+
+;; -mtune=<xxx> as an index into the processor_target_table or -1
+TargetVariable
+int rs6000_tune_index = -1
+
+;; Debug flags
+TargetVariable
+unsigned int rs6000_debug
+
+;; Save for target_flags_explicit
+TargetSave
+int rs6000_target_flags_explicit
+
mpower
Target Report RejectNegative Mask(POWER)
Use POWER instruction set
@@ -45,55 +148,55 @@ Target Report Mask(POWERPC64)
Use PowerPC-64 instruction set
mpowerpc-gpopt
-Target Report Mask(PPC_GPOPT)
+Target Report Mask(PPC_GPOPT) Save
Use PowerPC General Purpose group optional instructions
mpowerpc-gfxopt
-Target Report Mask(PPC_GFXOPT)
+Target Report Mask(PPC_GFXOPT) Save
Use PowerPC Graphics group optional instructions
mmfcrf
-Target Report Mask(MFCRF)
+Target Report Mask(MFCRF) Save
Use PowerPC V2.01 single field mfcr instruction
mpopcntb
-Target Report Mask(POPCNTB)
+Target Report Mask(POPCNTB) Save
Use PowerPC V2.02 popcntb instruction
mfprnd
-Target Report Mask(FPRND)
+Target Report Mask(FPRND) Save
Use PowerPC V2.02 floating point rounding instructions
mcmpb
-Target Report Mask(CMPB)
+Target Report Mask(CMPB) Save
Use PowerPC V2.05 compare bytes instruction
mmfpgpr
-Target Report Mask(MFPGPR)
+Target Report Mask(MFPGPR) Save
Use extended PowerPC V2.05 move floating point to/from GPR instructions
maltivec
-Target Report Mask(ALTIVEC)
+Target Report Mask(ALTIVEC) Save
Use AltiVec instructions
mhard-dfp
-Target Report Mask(DFP)
+Target Report Mask(DFP) Save
Use decimal floating point instructions
mmulhw
-Target Report Mask(MULHW)
+Target Report Mask(MULHW) Save
Use 4xx half-word multiply instructions
mdlmzb
-Target Report Mask(DLMZB)
+Target Report Mask(DLMZB) Save
Use 4xx string-search dlmzb instruction
mmultiple
-Target Report Mask(MULTIPLE)
+Target Report Mask(MULTIPLE) Save
Generate load/store multiple instructions
mstring
-Target Report Mask(STRING)
+Target Report Mask(STRING) Save
Generate string instructions for block moves
mnew-mnemonics
@@ -113,11 +216,11 @@ Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
Use hardware floating point
mpopcntd
-Target Report Mask(POPCNTD)
+Target Report Mask(POPCNTD) Save
Use PowerPC V2.06 popcntd instruction
mfriz
-Target Report Var(TARGET_FRIZ) Init(-1)
+Target Report Var(TARGET_FRIZ) Init(-1) Save
Under -ffast-math, generate a FRIZ instruction for (double)(long long) conversions
mveclibabi=
@@ -125,7 +228,7 @@ Target RejectNegative Joined Var(rs6000_veclibabi_name)
Vector library ABI to use
mvsx
-Target Report Mask(VSX)
+Target Report Mask(VSX) Save
Use vector/scalar (VSX) instructions
mvsx-scalar-double
@@ -165,7 +268,7 @@ Target Undocumented Report Var(TARGET_VECTORIZE_BUILTINS) Init(-1)
; Explicitly control whether we vectorize the builtins or not.
mno-update
-Target Report RejectNegative Mask(NO_UPDATE)
+Target Report RejectNegative Mask(NO_UPDATE) Save
Do not generate load/store with update instructions
mupdate
@@ -173,30 +276,30 @@ Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
Generate load/store with update instructions
mavoid-indexed-addresses
-Target Report Var(TARGET_AVOID_XFORM) Init(-1)
+Target Report Var(TARGET_AVOID_XFORM) Init(-1) Save
Avoid generation of indexed load/store instructions when possible
mtls-markers
-Target Report Var(tls_markers) Init(1)
+Target Report Var(tls_markers) Init(1) Save
Mark __tls_get_addr calls with argument info
msched-epilog
-Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1)
+Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1) Save
msched-prolog
-Target Report Var(TARGET_SCHED_PROLOG)
+Target Report Var(TARGET_SCHED_PROLOG) Save
Schedule the start and end of the procedure
maix-struct-return
-Target Report RejectNegative Var(aix_struct_return)
+Target Report RejectNegative Var(aix_struct_return) Save
Return all structures in memory (AIX default)
msvr4-struct-return
-Target Report RejectNegative Var(aix_struct_return,0)
+Target Report RejectNegative Var(aix_struct_return,0) Save
Return small structures in registers (SVR4 default)
mxl-compat
-Target Report Var(TARGET_XL_COMPAT)
+Target Report Var(TARGET_XL_COMPAT) Save
Conform more closely to IBM XLC semantics
mrecip
@@ -208,23 +311,23 @@ Target Report RejectNegative Joined
Generate software reciprocal divide and square root for better throughput.
mrecip-precision
-Target Report Mask(RECIP_PRECISION)
+Target Report Mask(RECIP_PRECISION) Save
Assume that the reciprocal estimate instructions provide more accuracy.
mno-fp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC)
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC) Save
Do not place floating point constants in TOC
mfp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0)
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0) Save
Place floating point constants in TOC
mno-sum-in-toc
-Target RejectNegative Var(TARGET_NO_SUM_IN_TOC)
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC) Save
Do not place symbol+offset constants in TOC
msum-in-toc
-Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0)
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0) Save
Place symbol+offset constants in TOC
; Output only one TOC entry per module. Normally linking fails if
@@ -243,7 +346,7 @@ Target Report
Put everything in the regular TOC
mvrsave
-Target Report Var(TARGET_ALTIVEC_VRSAVE)
+Target Report Var(TARGET_ALTIVEC_VRSAVE) Save
Generate VRSAVE instructions when generating AltiVec code
mvrsave=
@@ -251,11 +354,11 @@ Target RejectNegative Joined
-mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead
mblock-move-inline-limit=
-Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger
+Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger Save
Specify how many bytes should be moved inline before calling out to memcpy/memmove
misel
-Target Report Mask(ISEL)
+Target Report Mask(ISEL) Save
Generate isel instructions
misel=
@@ -267,7 +370,7 @@ Target
Generate SPE SIMD instructions on E500
mpaired
-Target Var(rs6000_paired_float)
+Target Var(rs6000_paired_float) Save
Generate PPC750CL paired-single instructions
mspe=
@@ -295,19 +398,19 @@ Target RejectNegative Joined
-mtraceback= Select full, part, or no traceback table
mlongcall
-Target Report Var(rs6000_default_long_calls)
+Target Report Var(rs6000_default_long_calls) Save
Avoid all range limits on call instructions
mgen-cell-microcode
-Target Report Var(rs6000_gen_cell_microcode) Init(-1)
+Target Report Var(rs6000_gen_cell_microcode) Init(-1) Save
Generate Cell microcode
mwarn-cell-microcode
-Target Var(rs6000_warn_cell_microcode) Init(0) Warning
+Target Var(rs6000_warn_cell_microcode) Init(0) Warning Save
Warn when a Cell microcoded instruction is emitted
mwarn-altivec-long
-Target Var(rs6000_warn_altivec_long) Init(1)
+Target Var(rs6000_warn_altivec_long) Init(1) Save
Warn about deprecated 'vector long ...' AltiVec type usage
mfloat-gprs=
@@ -331,19 +434,19 @@ Target RejectNegative Joined
Specify alignment of structure fields default/natural
mprioritize-restricted-insns=
-Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority)
+Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority) Save
Specify scheduling priority for dispatch slot restricted insns
msingle-float
-Target RejectNegative Var(rs6000_single_float)
+Target RejectNegative Var(rs6000_single_float) Save
Single-precision floating point unit
mdouble-float
-Target RejectNegative Var(rs6000_double_float)
+Target RejectNegative Var(rs6000_double_float) Save
Double-precision floating point unit
msimple-fpu
-Target RejectNegative Var(rs6000_simple_fpu)
+Target RejectNegative Var(rs6000_simple_fpu) Save
Floating point unit does not support divide & sqrt
mfpu=
@@ -351,7 +454,7 @@ Target RejectNegative Joined
-mfpu= Specify FP (sp, dp, sp-lite, dp-lite) (implies -mxilinx-fpu)
mxilinx-fpu
-Target Var(rs6000_xilinx_fpu)
+Target Var(rs6000_xilinx_fpu) Save
Specify Xilinx FPU.
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index e82a1c6..d557ce1 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -41,16 +41,6 @@
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mppc"
-/* Small data support types. */
-enum rs6000_sdata_type {
- SDATA_NONE, /* No small data support. */
- SDATA_DATA, /* Just put data in .sbss/.sdata, don't use relocs. */
- SDATA_SYSV, /* Use r13 to point to .sdata/.sbss. */
- SDATA_EABI /* Use r13 like above, r2 points to .sdata2/.sbss2. */
-};
-
-extern enum rs6000_sdata_type rs6000_sdata;
-
#define TARGET_TOC ((target_flags & MASK_64BIT) \
|| ((target_flags & (MASK_RELOCATABLE \
| MASK_MINIMAL_TOC)) \
@@ -70,10 +60,6 @@ extern enum rs6000_sdata_type rs6000_sdata;
#define TARGET_SECURE_PLT secure_plt
#endif
-extern const char *rs6000_abi_name;
-extern const char *rs6000_sdata_name;
-extern const char *rs6000_tls_size_string; /* For -mtls-size= */
-
#define SDATA_DEFAULT_SIZE 8
/* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt
index 29f3bdf..f1f987d 100644
--- a/gcc/config/rs6000/sysv4.opt
+++ b/gcc/config/rs6000/sysv4.opt
@@ -32,7 +32,7 @@ Target RejectNegative Joined
Specify bit size of immediate TLS offsets
mbit-align
-Target Report Var(TARGET_NO_BITFIELD_TYPE)
+Target Report Var(TARGET_NO_BITFIELD_TYPE) Save
Align to the base type of the bit-field
mstrict-align
@@ -74,7 +74,7 @@ Target RejectNegative
no description yet
mprototype
-Target Var(target_prototype)
+Target Var(target_prototype) Save
Assume all variable arg functions are prototyped
;; FIXME: Does nothing.
@@ -87,11 +87,11 @@ Target Report Mask(EABI)
Use EABI
mbit-word
-Target Report Var(TARGET_NO_BITFIELD_WORD)
+Target Report Var(TARGET_NO_BITFIELD_WORD) Save
Allow bit-fields to cross word boundaries
mregnames
-Target Var(rs6000_regnames)
+Target Var(rs6000_regnames) Save
Use alternate register names
;; This option does nothing and only exists because the compiler
@@ -137,9 +137,9 @@ Target RejectNegative
no description yet
msecure-plt
-Target Report RejectNegative Var(secure_plt, 1)
+Target Report RejectNegative Var(secure_plt, 1) Save
Generate code to use a non-exec PLT and GOT
mbss-plt
-Target Report RejectNegative Var(secure_plt, 0)
+Target Report RejectNegative Var(secure_plt, 0) Save
Generate code for old exec BSS PLT
diff --git a/gcc/configure b/gcc/configure
index c8d81d4..ec4ba8e 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -849,7 +849,8 @@ PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
-ac_subst_files='language_hooks'
+ac_subst_files='option_includes
+language_hooks'
ac_user_opts='
enable_option_checking
with_build_libsubdir
@@ -10638,8 +10639,10 @@ fi
# Convert extra_options into a form suitable for Makefile use.
extra_opt_files=
+all_opt_files=
for f in $extra_options; do
extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+ all_opt_files="$all_opt_files $srcdir/config/$f"
done
@@ -17283,7 +17286,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17286 "configure"
+#line 17289 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -17389,7 +17392,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17392 "configure"
+#line 17395 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -25672,6 +25675,7 @@ do
all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
if test -f $srcdir/$gcc_subdir/lang.opt; then
lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+ all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
fi
if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
@@ -25724,6 +25728,14 @@ do
done
# --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+
+
+# --------
# UNSORTED
# --------
@@ -27389,3 +27401,4 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/gcc/configure.ac b/gcc/configure.ac
index a61e5f1..0eb2d8b 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1382,8 +1382,10 @@ fi
# Convert extra_options into a form suitable for Makefile use.
extra_opt_files=
+all_opt_files=
for f in $extra_options; do
extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+ all_opt_files="$all_opt_files $srcdir/config/$f"
done
AC_SUBST(extra_opt_files)
@@ -4458,6 +4460,7 @@ changequote([,])dnl
all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
if test -f $srcdir/$gcc_subdir/lang.opt; then
lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+ all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
fi
if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
@@ -4508,6 +4511,14 @@ do
done
# --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+AC_SUBST_FILE(option_includes)
+
+# --------
# UNSORTED
# --------
@@ -4769,3 +4780,4 @@ done
],
[subdirs='$subdirs'])
AC_OUTPUT
+
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ccd0d91..28c25e1 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3272,6 +3272,8 @@ int core2_func (void) __attribute__ ((__target__ ("arch=core2")));
int sse3_func (void) __attribute__ ((__target__ ("sse3")));
@end smallexample
+@table @samp
+@item i386 target attributes
On the 386, the following options are allowed:
@table @samp
@@ -3414,19 +3416,195 @@ Specify which floating point unit to use. The
@code{target("fpmath=sse,387")} option must be specified as
@code{target("fpmath=sse+387")} because the comma would separate
different options.
+
+@item PowerPC target attributes
+On the PowerPC, the following options are allowed:
+
+@table @samp
+@item altivec
+@itemx no-altivec
+@cindex @code{target("altivec")} attribute
+Generate code that uses (does not use) AltiVec instructions. In
+32-bit code, you cannot enable Altivec instructions unless
+@option{-mabi=altivec} was used on the command line.
+
+@item cmpb
+@itemx no-cmpb
+@cindex @code{target("cmpb")} attribute
+Generate code that uses (does not use) the compare bytes instruction
+implemented on the POWER6 processor and other processors that support
+the PowerPC V2.05 architecture.
+
+@item dlmzb
+@itemx no-dlmzb
+@cindex @code{target("dlmzb")} attribute
+Generate code that uses (does not use) the string-search @samp{dlmzb}
+instruction on the IBM 405, 440, 464 and 476 processors. This instruction is
+generated by default when targetting those processors.
+
+@item fprnd
+@itemx no-fprnd
+@cindex @code{target("fprnd")} attribute
+Generate code that uses (does not use) the FP round to integer
+instructions implemented on the POWER5+ processor and other processors
+that support the PowerPC V2.03 architecture.
+
+@item hard-dfp
+@itemx no-hard-dfp
+@cindex @code{target("hard-dfp")} attribute
+Generate code that uses (does not use) the decimal floating point
+instructions implemented on some POWER processors.
+
+@item isel
+@itemx no-isel
+@cindex @code{target("isel")} attribute
+Generate code that uses (does not use) ISEL instruction.
+
+@item mfcrf
+@itemx no-mfcrf
+@cindex @code{target("mfcrf")} attribute
+Generate code that uses (does not use) the move from condition
+register field instruction implemented on the POWER4 processor and
+other processors that support the PowerPC V2.01 architecture.
+
+@item mfpgpr
+@itemx no-mfpgpr
+@cindex @code{target("mfpgpr")} attribute
+Generate code that uses (does not use) the FP move to/from general
+purpose register instructions implemented on the POWER6X processor and
+other processors that support the extended PowerPC V2.05 architecture.
+
+@item mulhw
+@itemx no-mulhw
+@cindex @code{target("mulhw")} attribute
+Generate code that uses (does not use) the half-word multiply and
+multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors.
+These instructions are generated by default when targetting those
+processors.
+
+@item multiple
+@itemx no-multiple
+@cindex @code{target("multiple")} attribute
+Generate code that uses (does not use) the load multiple word
+instructions and the store multiple word instructions.
+
+@item update
+@itemx no-update
+@cindex @code{target("update")} attribute
+Generate code that uses (does not use) the load or store instructions
+that update the base register to the address of the calculated memory
+location.
+
+@item popcntb
+@itemx no-popcntb
+@cindex @code{target("popcntb")} attribute
+Generate code that uses (does not use) the popcount and double
+precision FP reciprocal estimate instruction implemented on the POWER5
+processor and other processors that support the PowerPC V2.02
+architecture.
+
+@item popcntd
+@itemx no-popcntd
+@cindex @code{target("popcntd")} attribute
+Generate code that uses (does not use) the popcount instruction
+implemented on the POWER7 processor and other processors that support
+the PowerPC V2.06 architecture.
+
+@item powerpc-gfxopt
+@itemx no-powerpc-gfxopt
+@cindex @code{target("powerpc-gfxopt")} attribute
+Generate code that uses (does not use) the optional PowerPC
+architecture instructions in the Graphics group, including
+floating-point select.
+
+@item powerpc-gpopt
+@itemx no-powerpc-gpopt
+@cindex @code{target("powerpc-gpopt")} attribute
+Generate code that uses (does not use) the optional PowerPC
+architecture instructions in the General Purpose group, including
+floating-point square root.
+
+@item recip-precision
+@itemx no-recip-precision
+@cindex @code{target("recip-precision")} attribute
+Assume (do not assume) that the reciprocal estimate instructions
+provide higher precision estimates than is mandated by the powerpc
+ABI.
+
+@item string
+@itemx no-string
+@cindex @code{target("string")} attribute
+Generate code that uses (does not use) the load string instructions
+and the store string word instructions to save multiple registers and
+do small block moves.
+
+@item vsx
+@itemx no-vsx
+@cindex @code{target("vsx")} attribute
+Generate code that uses (does not use) vector/scalar (VSX)
+instructions, and also enable the use of built-in functions that allow
+more direct access to the VSX instruction set. In 32-bit code, you
+cannot enable VSX or Altivec instructions unless
+@option{-mabi=altivec} was used on the command line.
+
+@item friz
+@itemx no-friz
+@cindex @code{target("friz")} attribute
+Generate (do not generate) the @code{friz} instruction when the
+@option{-funsafe-math-optimizations} option is used to optimize
+rounding a floating point value to 64-bit integer and back to floating
+point. The @code{friz} instruction does not return the same value if
+the floating point number is too large to fit in an integer.
+
+@item avoid-indexed-addresses
+@itemx no-avoid-indexed-addresses
+@cindex @code{target("avoid-indexed-addresses")} attribute
+Generate code that tries to avoid (not avoid) the use of indexed load
+or store instructions.
+
+@item paired
+@itemx no-paired
+@cindex @code{target("paired")} attribute
+Generate code that uses (does not use) the generation of PAIRED simd
+instructions.
+
+@item longcall
+@itemx no-longcall
+@cindex @code{target("longcall")} attribute
+Generate code that assumes (does not assume) that all calls are far
+away so that a longer more expensive calling sequence is required.
+
+@item cpu=@var{CPU}
+@cindex @code{target("cpu=@var{CPU}")} attribute
+Specify the architecture to generate code for in compiling the
+function. If you select @code{"target("cpu=power7)"} attribute when
+generating 32-bit code, VSX and Altivec instructions are not generated
+unless you use the @option{-mabi=altivec} option on the command line.
+
+@item tune=@var{TUNE}
+@cindex @code{target("tune=@var{TUNE}")} attribute
+Specify the architecture to tune for in compiling the function. If
+you do not specify the @code{target("tune=@var{TUNE}")} attribute and
+you do specifiy the @code{target("cpu=@var{CPU}")} attribute,
+compilation will tune for the @var{CPU} architecture, and not the
+default tuning specified on the command line.
+@end table
+@end table
@end table
-On the 386, you can use either multiple strings to specify multiple
-options, or you can separate the option with a comma (@code{,}).
+On the 386/x86_64 and PowerPC backends, you can use either multiple
+strings to specify multiple options, or you can separate the option
+with a comma (@code{,}).
-On the 386, the inliner will not inline a function that has different
-target options than the caller, unless the callee has a subset of the
-target options of the caller. For example a function declared with
-@code{target("sse3")} can inline a function with
-@code{target("sse2")}, since @code{-msse3} implies @code{-msse2}.
+On the 386/x86_64 and PowerPC backends, the inliner will not inline a
+function that has different target options than the caller, unless the
+callee has a subset of the target options of the caller. For example
+a function declared with @code{target("sse3")} can inline a function
+with @code{target("sse2")}, since @code{-msse3} implies @code{-msse2}.
The @code{target} attribute is not implemented in GCC versions earlier
-than 4.4, and at present only the 386 uses it.
+than 4.4 for the i386/x86_64 and 4.6 for the PowerPC backends. It is
+not currently implemented for other backends.
@item tiny_data
@cindex tiny data section on the H8/300H and H8S
@@ -13001,9 +13179,9 @@ function. The parenthesis around the options is optional.
@xref{Function Attributes}, for more information about the
@code{target} attribute and the attribute syntax.
-The @samp{#pragma GCC target} pragma is not implemented in GCC
-versions earlier than 4.4, and is currently only implemented for the
-386 and x86_64 backends.
+The @code{#pragma GCC target} attribute is not implemented in GCC versions earlier
+than 4.4 for the i386/x86_64 and 4.6 for the PowerPC backends. At
+present, it is not implemented for other backends.
@end table
@table @code
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0aebe45..e8d1d1d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -15614,8 +15614,11 @@ is enabled by default when targetting Power6 and disabled otherwise.
@opindex mfused-madd
@opindex mno-fused-madd
Generate code that uses (does not use) the floating point multiply and
-accumulate instructions. These instructions are generated by default if
-hardware floating is used.
+accumulate instructions. These instructions are generated by default
+if hardware floating point is used. The machine dependent
+@option{-mfused-madd} option is now mapped to the machine independent
+@option{-ffp-contract=fast} option, and @option{-mno-fused-madd} is
+mapped to @option{-ffp-contract=off}.
@item -mmulhw
@itemx -mno-mulhw
diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi
index 0538393..8c5c639 100644
--- a/gcc/doc/options.texi
+++ b/gcc/doc/options.texi
@@ -52,6 +52,32 @@ for variables set in option handlers rather than referenced by
@code{Var} properties.
@item
+A variable record to define a variable used to store option
+information. These records have two fields: the string
+@samp{TargetVariable}, and a declaration of the type and name of the
+variable, optionally with an initializer (but without any trailing
+@samp{;}). @samp{TargetVariable} is a combination of @samp{Variable}
+and @samp{TargetSave} records in that the variable is defined in the
+@code{gcc_options} structure, but these variables are also stored in
+the @code{cl_target_option} structure. The variables are saved in the
+target save code and restored in the target restore code.
+
+@item
+A variable record to record any additional files that the
+@file{options.h} file should include. This is useful to provide
+enumeration or structure definitions needed for target variables.
+These records have two fields: the string @samp{HeaderInclude} and the
+name of the include file.
+
+@item
+A variable record to record any additional files that the
+@file{options.c} file should include. This is useful to provide
+inline functions needed for target variables and/or @code{#ifdef}
+sequences to properly set up the initialization. These records have
+two fields: the string @samp{SourceInclude} and the name of the
+include file.
+
+@item
An option definition record. These records have the following fields:
@enumerate
@item
diff --git a/gcc/opt-include.awk b/gcc/opt-include.awk
new file mode 100644
index 0000000..31169ae
--- /dev/null
+++ b/gcc/opt-include.awk
@@ -0,0 +1,30 @@
+# Copyright (C) 2010
+# Free Software Foundation, Inc.
+# Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records and emits the include files
+# listed by the HeaderInclude directive.
+
+BEGIN {
+ h_next = 0
+ c_next = 0
+}
+
+(h_next != 0) { print "OPTIONS_H_EXTRA += $(srcdir)/" $1; h_next = 0 }
+(c_next != 0) { print "OPTIONS_C_EXTRA += $(srcdir)/" $1; c_next = 0 }
+/^HeaderInclude$/ { h_next = 1; c_next = 0 }
+/^SourceInclude$/ { h_next = 0; c_next = 1 }
diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk
index 97bbd43..3bf0b8e 100644
--- a/gcc/optc-gen.awk
+++ b/gcc/optc-gen.awk
@@ -31,7 +31,10 @@ BEGIN {
n_langs = 0
n_target_save = 0
n_extra_vars = 0
- quote = "\042"
+ n_extra_target_vars = 0
+ n_extra_c_includes = 0
+ n_extra_h_includes = 0
+ quote = "\042"
comma = ","
FS=SUBSEP
# Default the name of header created from opth-gen.awk to options.h
@@ -53,6 +56,30 @@ BEGIN {
extra_vars[n_extra_vars] = $2
n_extra_vars++
}
+ else if ($1 == "TargetVariable") {
+ # Combination of TargetSave and Variable
+ extra_vars[n_extra_vars] = $2
+ n_extra_vars++
+
+ var = $2
+ sub(" *=.*", "", var)
+ orig_var = var
+ name = var
+ type = var
+ sub("^.*[ *]", "", name)
+ sub(" *" name "$", "", type)
+ target_save_decl[n_target_save] = type " x_" name
+ n_target_save++
+
+ extra_target_vars[n_extra_target_vars] = name
+ n_extra_target_vars++;
+ }
+ else if ($1 == "HeaderInclude") {
+ extra_h_includes[n_extra_h_includes++] = $2;
+ }
+ else if ($1 == "SourceInclude") {
+ extra_c_includes[n_extra_c_includes++] = $2;
+ }
else {
name = opt_args("Mask", $1)
if (name == "") {
@@ -82,7 +109,17 @@ print "#include " quote "target.h" quote
print "#endif /* GCC_DRIVER */"
print ""
+if (n_extra_c_includes > 0) {
+ for (i = 0; i < n_extra_c_includes; i++) {
+ print "#include " quote extra_c_includes[i] quote
+ }
+ print ""
+}
+
have_save = 0;
+if (n_extra_target_vars)
+ have_save = 1
+
print "const struct gcc_options global_options_init =\n{"
for (i = 0; i < n_extra_vars; i++) {
var = extra_vars[i]
@@ -305,11 +342,13 @@ print "{";
n_opt_char = 2;
n_opt_short = 0;
n_opt_int = 0;
+n_opt_enum = 1;
n_opt_other = 0;
var_opt_char[0] = "optimize";
var_opt_char[1] = "optimize_size";
var_opt_range["optimize"] = "0, 255";
var_opt_range["optimize_size"] = "0, 255";
+var_opt_enum[0] = "flag_fp_contract_mode";
# Sort by size to mimic how the structure is laid out to be friendlier to the
# cache.
@@ -331,6 +370,9 @@ for (i = 0; i < n_opts; i++) {
else if (otype ~ "^((un)?signed +)?short *$")
var_opt_short[n_opt_short++] = name;
+ else if (otype ~ ("^enum +[_" alnum "]+ *"))
+ var_opt_enum[n_opt_enum++] = name;
+
else if (otype ~ "^((un)?signed +)?char *$") {
var_opt_char[n_opt_char++] = name;
if (otype ~ "^unsigned +char *$")
@@ -358,6 +400,10 @@ for (i = 0; i < n_opt_int; i++) {
print " ptr->x_" var_opt_int[i] " = opts->x_" var_opt_int[i] ";";
}
+for (i = 0; i < n_opt_enum; i++) {
+ print " ptr->x_" var_opt_enum[i] " = opts->x_" var_opt_enum[i] ";";
+}
+
for (i = 0; i < n_opt_short; i++) {
print " ptr->x_" var_opt_short[i] " = opts->x_" var_opt_short[i] ";";
}
@@ -382,6 +428,10 @@ for (i = 0; i < n_opt_int; i++) {
print " opts->x_" var_opt_int[i] " = ptr->x_" var_opt_int[i] ";";
}
+for (i = 0; i < n_opt_enum; i++) {
+ print " opts->x_" var_opt_enum[i] " = ptr->x_" var_opt_enum[i] ";";
+}
+
for (i = 0; i < n_opt_short; i++) {
print " opts->x_" var_opt_short[i] " = ptr->x_" var_opt_short[i] ";";
}
@@ -420,6 +470,14 @@ for (i = 0; i < n_opt_int; i++) {
print "";
}
+for (i = 0; i < n_opt_enum; i++) {
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_enum[i] "\",";
+ print " (int) ptr->x_" var_opt_enum[i] ");";
+ print "";
+}
+
for (i = 0; i < n_opt_short; i++) {
print " if (ptr->x_" var_opt_short[i] ")";
print " fprintf (file, \"%*s%s (%#x)\\n\",";
@@ -449,6 +507,7 @@ print "{";
n_target_char = 0;
n_target_short = 0;
n_target_int = 0;
+n_target_enum = 0;
n_target_other = 0;
if (have_save) {
@@ -469,6 +528,9 @@ if (have_save) {
else if (otype ~ "^((un)?signed +)?short *$")
var_target_short[n_target_short++] = name;
+ else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+ var_target_enum[n_target_enum++] = name;
+
else if (otype ~ "^((un)?signed +)?char *$") {
var_target_char[n_target_char++] = name;
if (otype ~ "^unsigned +char *$")
@@ -500,10 +562,18 @@ print " if (targetm.target_option.save)";
print " targetm.target_option.save (ptr);";
print "";
+for (i = 0; i < n_extra_target_vars; i++) {
+ print " ptr->x_" extra_target_vars[i] " = opts->x_" extra_target_vars[i] ";";
+}
+
for (i = 0; i < n_target_other; i++) {
print " ptr->x_" var_target_other[i] " = opts->x_" var_target_other[i] ";";
}
+for (i = 0; i < n_target_enum; i++) {
+ print " ptr->x_" var_target_enum[i] " = opts->x_" var_target_enum[i] ";";
+}
+
for (i = 0; i < n_target_int; i++) {
print " ptr->x_" var_target_int[i] " = opts->x_" var_target_int[i] ";";
}
@@ -524,10 +594,18 @@ print "void";
print "cl_target_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)";
print "{";
+for (i = 0; i < n_extra_target_vars; i++) {
+ print " opts->x_" extra_target_vars[i] " = ptr->x_" extra_target_vars[i] ";";
+}
+
for (i = 0; i < n_target_other; i++) {
print " opts->x_" var_target_other[i] " = ptr->x_" var_target_other[i] ";";
}
+for (i = 0; i < n_target_enum; i++) {
+ print " opts->x_" var_target_enum[i] " = ptr->x_" var_target_enum[i] ";";
+}
+
for (i = 0; i < n_target_int; i++) {
print " opts->x_" var_target_int[i] " = ptr->x_" var_target_int[i] ";";
}
@@ -566,6 +644,15 @@ for (i = 0; i < n_target_other; i++) {
print "";
}
+for (i = 0; i < n_target_enum; i++) {
+ print " if (ptr->x_" var_target_enum[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_enum[i] "\",";
+ print " ptr->x_" var_target_enum[i] ");";
+ print "";
+}
+
for (i = 0; i < n_target_int; i++) {
print " if (ptr->x_" var_target_int[i] ")";
print " fprintf (file, \"%*s%s (%#x)\\n\",";
diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk
index 4588a53..9fafb99 100644
--- a/gcc/opth-gen.awk
+++ b/gcc/opth-gen.awk
@@ -29,7 +29,12 @@ BEGIN {
n_langs = 0
n_target_save = 0
n_extra_vars = 0
+ n_extra_target_vars = 0
n_extra_masks = 0
+ n_extra_c_includes = 0
+ n_extra_h_includes = 0
+ have_save = 0;
+ quote = "\042"
FS=SUBSEP
}
@@ -48,6 +53,30 @@ BEGIN {
extra_vars[n_extra_vars] = $2
n_extra_vars++
}
+ else if ($1 == "TargetVariable") {
+ # Combination of TargetSave and Variable
+ extra_vars[n_extra_vars] = $2
+ n_extra_vars++
+
+ var = $2
+ sub(" *=.*", "", var)
+ orig_var = var
+ name = var
+ type = var
+ sub("^.*[ *]", "", name)
+ sub(" *" name "$", "", type)
+ target_save_decl[n_target_save] = type " x_" name
+ n_target_save++
+
+ extra_target_vars[n_extra_target_vars] = name
+ n_extra_target_vars++
+ }
+ else if ($1 == "HeaderInclude") {
+ extra_h_includes[n_extra_h_includes++] = $2;
+ }
+ else if ($1 == "SourceInclude") {
+ extra_c_includes[n_extra_c_includes++] = $2;
+ }
else {
name = opt_args("Mask", $1)
if (name == "") {
@@ -73,11 +102,21 @@ print ""
print "#include \"flag-types.h\""
print ""
-have_save = 0;
+if (n_extra_h_includes > 0) {
+ for (i = 0; i < n_extra_h_includes; i++) {
+ print "#include " quote extra_h_includes[i] quote
+ }
+ print ""
+}
print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
print "#ifndef GENERATOR_FILE"
-print "struct gcc_options\n{"
+print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
+print "struct GTY(()) gcc_options"
+print "#else"
+print "struct gcc_options"
+print "#endif"
+print "{"
print "#endif"
for (i = 0; i < n_extra_vars; i++) {
@@ -155,9 +194,11 @@ print "{";
n_opt_char = 2;
n_opt_short = 0;
n_opt_int = 0;
+n_opt_enum = 1;
n_opt_other = 0;
var_opt_char[0] = "unsigned char x_optimize";
var_opt_char[1] = "unsigned char x_optimize_size";
+var_opt_enum[0] = "enum fp_contract_mode x_flag_fp_contract_mode";
for (i = 0; i < n_opts; i++) {
if (flag_set_p("Optimization", flags[i])) {
@@ -179,6 +220,9 @@ for (i = 0; i < n_opts; i++) {
else if (otype ~ "^((un)?signed +)?char *$")
var_opt_char[n_opt_char++] = otype "x_" name;
+ else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+ var_opt_enum[n_opt_enum++] = otype "x_" name;
+
else
var_opt_other[n_opt_other++] = otype "x_" name;
}
@@ -192,6 +236,10 @@ for (i = 0; i < n_opt_int; i++) {
print " " var_opt_int[i] ";";
}
+for (i = 0; i < n_opt_enum; i++) {
+ print " " var_opt_enum[i] ";";
+}
+
for (i = 0; i < n_opt_short; i++) {
print " " var_opt_short[i] ";";
}
@@ -211,6 +259,7 @@ print "{";
n_target_char = 0;
n_target_short = 0;
n_target_int = 0;
+n_target_enum = 0;
n_target_other = 0;
for (i = 0; i < n_target_save; i++) {
@@ -223,6 +272,9 @@ for (i = 0; i < n_target_save; i++) {
else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_ " alnum "]+$")
var_target_char[n_target_char++] = target_save_decl[i];
+ else if (target_save_decl[i] ~ ("^enum +[_" alnum "]+ +[_" alnum "]+$")) {
+ var_target_enum[n_target_enum++] = target_save_decl[i];
+ }
else
var_target_other[n_target_other++] = target_save_decl[i];
}
@@ -248,6 +300,9 @@ if (have_save) {
else if (otype ~ "^((un)?signed +)?char *$")
var_target_char[n_target_char++] = otype "x_" name;
+ else if (otype ~ ("^enum +[_" alnum "]+ +[_" alnum "]+"))
+ var_target_enum[n_target_enum++] = otype "x_" name;
+
else
var_target_other[n_target_other++] = otype "x_" name;
}
@@ -260,6 +315,10 @@ for (i = 0; i < n_target_other; i++) {
print " " var_target_other[i] ";";
}
+for (i = 0; i < n_target_enum; i++) {
+ print " " var_target_enum[i] ";";
+}
+
for (i = 0; i < n_target_int; i++) {
print " " var_target_int[i] ";";
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2e58884..d6c4d2b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2010-11-19 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/ppc-target-1.c: New file to test target
+ attributes on PowerPC.
+ * gcc.target/powerpc/ppc-target-2.c: Ditto.
+ * gcc.target/powerpc/ppc-target-3.c: Ditto.
+
2010-11-19 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/attributes/proto-attribute-1.m: Updated.
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
new file mode 100644
index 0000000..c98666c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
@@ -0,0 +1,59 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ffast-math -mcpu=power5 -mabi=altivec" } */
+/* { dg-final { scan-assembler-times "fabs" 3 } } */
+/* { dg-final { scan-assembler-times "fnabs" 3 } } */
+/* { dg-final { scan-assembler-times "fsel" 3 } } */
+/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
+/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+
+double normal1 (double, double);
+double power5 (double, double) __attribute__((__target__("cpu=power5")));
+double power6 (double, double) __attribute__((__target__("cpu=power6")));
+double power6x (double, double) __attribute__((__target__("cpu=power6x")));
+double power7 (double, double) __attribute__((__target__("cpu=power7")));
+double power7n (double, double) __attribute__((__target__("cpu=power7,no-vsx")));
+double normal2 (double, double);
+
+/* fabs/fnabs/fsel */
+double normal1 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fabs/fnabs/fsel */
+double power5 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power6 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power6x (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* xscpsgndp */
+double power7 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power7n (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fabs/fnabs/fsel */
+double normal2 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
new file mode 100644
index 0000000..8ef95b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
@@ -0,0 +1,41 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ffast-math -mcpu=power5 -mabi=altivec" } */
+/* { dg-final { scan-assembler-times "fabs" 3 } } */
+/* { dg-final { scan-assembler-times "fnabs" 3 } } */
+/* { dg-final { scan-assembler-times "fsel" 3 } } */
+/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
+/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+
+/* fabs/fnabs/fsel */
+double normal1 (double a, double b) { return __builtin_copysign (a, b); }
+
+#pragma GCC push_options
+#pragma GCC target ("cpu=power5")
+/* fabs/fnabs/fsel */
+double power5 (double a, double b) { return __builtin_copysign (a, b); }
+#pragma GCC pop_options
+
+#pragma GCC target ("cpu=power6")
+/* fcpsgn */
+double power6 (double a, double b) { return __builtin_copysign (a, b); }
+#pragma GCC reset_options
+
+#pragma GCC target ("cpu=power6x")
+/* fcpsgn */
+double power6x (double a, double b) { return __builtin_copysign (a, b); }
+#pragma GCC reset_options
+
+#pragma GCC target ("cpu=power7")
+/* xscpsgndp */
+double power7 (double a, double b) { return __builtin_copysign (a, b); }
+#pragma GCC reset_options
+
+#pragma GCC target ("cpu=power7,no-vsx")
+/* fcpsgn */
+double power7n (double a, double b) { return __builtin_copysign (a, b); }
+#pragma GCC reset_options
+
+/* fabs/fnabs/fsel */
+double normal2 (double a, double b) { return __builtin_copysign (a, b); }
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-3.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-3.c
new file mode 100644
index 0000000..286f31f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-3.c
@@ -0,0 +1,62 @@
+/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ffast-math -mcpu=power5 -mabi=no-altivec" } */
+/* { dg-final { scan-assembler-times "fabs" 3 } } */
+/* { dg-final { scan-assembler-times "fnabs" 3 } } */
+/* { dg-final { scan-assembler-times "fsel" 3 } } */
+/* { dg-final { scan-assembler-times "fcpsgn" 4 } } */
+/* { dg-final { scan-assembler-not "xscpsgndp" } } */
+
+/* Like ppc-target-1.c, but do not enable the altivec abi on 32-bit, so the
+ power7 code should generate fcpsgn and not xscpsgndp. */
+
+double normal1 (double, double);
+double power5 (double, double) __attribute__((__target__("cpu=power5")));
+double power6 (double, double) __attribute__((__target__("cpu=power6")));
+double power6x (double, double) __attribute__((__target__("cpu=power6x")));
+double power7 (double, double) __attribute__((__target__("cpu=power7")));
+double power7n (double, double) __attribute__((__target__("cpu=power7,no-vsx")));
+double normal2 (double, double);
+
+/* fabs/fnabs/fsel */
+double normal1 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fabs/fnabs/fsel */
+double power5 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power6 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power6x (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* xscpsgndp */
+double power7 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fcpsgn */
+double power7n (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* fabs/fnabs/fsel */
+double normal2 (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}