diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-05-20 08:22:38 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-05-20 08:22:38 +0000 |
commit | ccf4f3ae98386198926269817844b5bb67d3ebe4 (patch) | |
tree | 15db9a73406c618d2f18f1e9696a3f9549e5ace6 /gcc/config | |
parent | 79fb55a1f085a3c03a9168b97773ddd9a4ad054a (diff) | |
download | gcc-ccf4f3ae98386198926269817844b5bb67d3ebe4.tar.gz |
2011-05-20 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 173935 using svnmerge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@173937 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
43 files changed, 1763 insertions, 1789 deletions
diff --git a/gcc/config/arm/arm-fpus.def b/gcc/config/arm/arm-fpus.def new file mode 100644 index 00000000000..9f7e62acc4b --- /dev/null +++ b/gcc/config/arm/arm-fpus.def @@ -0,0 +1,48 @@ +/* ARM FPU variants. + Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + + 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. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* Before using #include to read this file, define a macro: + + ARM_FPU(NAME, MODEL, REV, VFP_REGS, NEON, FP16) + + The arguments are the fields of struct arm_fpu_desc. + + genopt.sh assumes no whitespace up to the first "," in each entry. */ + +ARM_FPU("fpa", ARM_FP_MODEL_FPA, 0, VFP_NONE, false, false) +ARM_FPU("fpe2", ARM_FP_MODEL_FPA, 2, VFP_NONE, false, false) +ARM_FPU("fpe3", ARM_FP_MODEL_FPA, 3, VFP_NONE, false, false) +ARM_FPU("maverick", ARM_FP_MODEL_MAVERICK, 0, VFP_NONE, false, false) +ARM_FPU("vfp", ARM_FP_MODEL_VFP, 2, VFP_REG_D16, false, false) +ARM_FPU("vfpv3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false) +ARM_FPU("vfpv3-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, true) +ARM_FPU("vfpv3-d16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, false) +ARM_FPU("vfpv3-d16-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, true) +ARM_FPU("vfpv3xd", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, false) +ARM_FPU("vfpv3xd-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, true) +ARM_FPU("neon", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , false) +ARM_FPU("neon-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true, true) +ARM_FPU("vfpv4", ARM_FP_MODEL_VFP, 4, VFP_REG_D32, false, true) +ARM_FPU("vfpv4-d16", ARM_FP_MODEL_VFP, 4, VFP_REG_D16, false, true) +ARM_FPU("fpv4-sp-d16", ARM_FP_MODEL_VFP, 4, VFP_REG_SINGLE, false, true) +ARM_FPU("neon-vfpv4", ARM_FP_MODEL_VFP, 4, VFP_REG_D32, true, true) +/* Compatibility aliases. */ +ARM_FPU("vfp3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false) diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h index f9f18036b92..c35224eaf5c 100644 --- a/gcc/config/arm/arm-opts.h +++ b/gcc/config/arm/arm-opts.h @@ -33,4 +33,39 @@ enum processor_type arm_none }; +/* Which __fp16 format to use. + The enumeration values correspond to the numbering for the + Tag_ABI_FP_16bit_format attribute. + */ +enum arm_fp16_format_type +{ + ARM_FP16_FORMAT_NONE = 0, + ARM_FP16_FORMAT_IEEE = 1, + ARM_FP16_FORMAT_ALTERNATIVE = 2 +}; + +/* Which ABI to use. */ +enum arm_abi_type +{ + ARM_ABI_APCS, + ARM_ABI_ATPCS, + ARM_ABI_AAPCS, + ARM_ABI_IWMMXT, + ARM_ABI_AAPCS_LINUX +}; + +enum float_abi_type +{ + ARM_FLOAT_ABI_SOFT, + ARM_FLOAT_ABI_SOFTFP, + ARM_FLOAT_ABI_HARD +}; + +/* Which thread pointer access sequence to use. */ +enum arm_tp_type { + TP_AUTO, + TP_SOFT, + TP_CP15 +}; + #endif diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt index 36cf2019682..f984480a01e 100644 --- a/gcc/config/arm/arm-tables.opt +++ b/gcc/config/arm/arm-tables.opt @@ -1,5 +1,6 @@ ; -*- buffer-read-only: t -*- -; Generated automatically by genopt.sh from arm-cores.def and arm-arches.def. +; Generated automatically by genopt.sh from arm-cores.def, arm-arches.def +; and arm-fpus.def. ; Copyright (C) 2011 Free Software Foundation, Inc. ; @@ -339,3 +340,61 @@ Enum(arm_arch) String(iwmmxt) Value(23) EnumValue Enum(arm_arch) String(iwmmxt2) Value(24) +Enum +Name(arm_fpu) Type(int) +Known ARM FPUs (for use with the -mfpu= option): + +EnumValue +Enum(arm_fpu) String(fpa) Value(0) + +EnumValue +Enum(arm_fpu) String(fpe2) Value(1) + +EnumValue +Enum(arm_fpu) String(fpe3) Value(2) + +EnumValue +Enum(arm_fpu) String(maverick) Value(3) + +EnumValue +Enum(arm_fpu) String(vfp) Value(4) + +EnumValue +Enum(arm_fpu) String(vfpv3) Value(5) + +EnumValue +Enum(arm_fpu) String(vfpv3-fp16) Value(6) + +EnumValue +Enum(arm_fpu) String(vfpv3-d16) Value(7) + +EnumValue +Enum(arm_fpu) String(vfpv3-d16-fp16) Value(8) + +EnumValue +Enum(arm_fpu) String(vfpv3xd) Value(9) + +EnumValue +Enum(arm_fpu) String(vfpv3xd-fp16) Value(10) + +EnumValue +Enum(arm_fpu) String(neon) Value(11) + +EnumValue +Enum(arm_fpu) String(neon-fp16) Value(12) + +EnumValue +Enum(arm_fpu) String(vfpv4) Value(13) + +EnumValue +Enum(arm_fpu) String(vfpv4-d16) Value(14) + +EnumValue +Enum(arm_fpu) String(fpv4-sp-d16) Value(15) + +EnumValue +Enum(arm_fpu) String(neon-vfpv4) Value(16) + +EnumValue +Enum(arm_fpu) String(vfp3) Value(17) + diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 4f9c2aa7063..47c7a3a4ca9 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -636,21 +636,6 @@ int arm_fpu_attr; /* Which floating popint hardware to use. */ const struct arm_fpu_desc *arm_fpu_desc; -/* Whether to use floating point hardware. */ -enum float_abi_type arm_float_abi; - -/* Which __fp16 format to use. */ -enum arm_fp16_format_type arm_fp16_format; - -/* Which ABI to use. */ -enum arm_abi_type arm_abi; - -/* Which thread pointer model to use. */ -enum arm_tp_type target_thread_pointer = TP_AUTO; - -/* Used to parse -mstructure_size_boundary command line option. */ -int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY; - /* Used for Thumb call_via trampolines. */ rtx thumb_call_via_label[14]; static int thumb_call_reg_needed; @@ -954,80 +939,13 @@ char arm_arch_name[] = "__ARM_ARCH_0UNK__"; static const struct arm_fpu_desc all_fpus[] = { - {"fpa", ARM_FP_MODEL_FPA, 0, VFP_NONE, false, false}, - {"fpe2", ARM_FP_MODEL_FPA, 2, VFP_NONE, false, false}, - {"fpe3", ARM_FP_MODEL_FPA, 3, VFP_NONE, false, false}, - {"maverick", ARM_FP_MODEL_MAVERICK, 0, VFP_NONE, false, false}, - {"vfp", ARM_FP_MODEL_VFP, 2, VFP_REG_D16, false, false}, - {"vfpv3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false}, - {"vfpv3-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, true}, - {"vfpv3-d16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, false}, - {"vfpv3-d16-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, true}, - {"vfpv3xd", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, false}, - {"vfpv3xd-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, true}, - {"neon", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , false}, - {"neon-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , true }, - {"vfpv4", ARM_FP_MODEL_VFP, 4, VFP_REG_D32, false, true}, - {"vfpv4-d16", ARM_FP_MODEL_VFP, 4, VFP_REG_D16, false, true}, - {"fpv4-sp-d16", ARM_FP_MODEL_VFP, 4, VFP_REG_SINGLE, false, true}, - {"neon-vfpv4", ARM_FP_MODEL_VFP, 4, VFP_REG_D32, true, true}, - /* Compatibility aliases. */ - {"vfp3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false}, -}; - - -struct float_abi -{ - const char * name; - enum float_abi_type abi_type; +#define ARM_FPU(NAME, MODEL, REV, VFP_REGS, NEON, FP16) \ + { NAME, MODEL, REV, VFP_REGS, NEON, FP16 }, +#include "arm-fpus.def" +#undef ARM_FPU }; -/* Available values for -mfloat-abi=. */ - -static const struct float_abi all_float_abis[] = -{ - {"soft", ARM_FLOAT_ABI_SOFT}, - {"softfp", ARM_FLOAT_ABI_SOFTFP}, - {"hard", ARM_FLOAT_ABI_HARD} -}; - - -struct fp16_format -{ - const char *name; - enum arm_fp16_format_type fp16_format_type; -}; - - -/* Available values for -mfp16-format=. */ - -static const struct fp16_format all_fp16_formats[] = -{ - {"none", ARM_FP16_FORMAT_NONE}, - {"ieee", ARM_FP16_FORMAT_IEEE}, - {"alternative", ARM_FP16_FORMAT_ALTERNATIVE} -}; - - -struct abi_name -{ - const char *name; - enum arm_abi_type abi_type; -}; - - -/* Available values for -mabi=. */ - -static const struct abi_name arm_all_abis[] = -{ - {"apcs-gnu", ARM_ABI_APCS}, - {"atpcs", ARM_ABI_ATPCS}, - {"aapcs", ARM_ABI_AAPCS}, - {"iwmmxt", ARM_ABI_IWMMXT}, - {"aapcs-linux", ARM_ABI_AAPCS_LINUX} -}; - /* Supported TLS relocations. */ enum tls_reloc { @@ -1311,8 +1229,6 @@ arm_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, static void arm_option_override (void) { - unsigned i; - if (global_options_set.x_arm_arch_option) arm_selected_arch = &all_architectures[arm_arch_option]; @@ -1447,39 +1363,6 @@ arm_option_override (void) tune_flags = arm_selected_tune->flags; current_tune = arm_selected_tune->tune; - if (target_fp16_format_name) - { - for (i = 0; i < ARRAY_SIZE (all_fp16_formats); i++) - { - if (streq (all_fp16_formats[i].name, target_fp16_format_name)) - { - arm_fp16_format = all_fp16_formats[i].fp16_format_type; - break; - } - } - if (i == ARRAY_SIZE (all_fp16_formats)) - error ("invalid __fp16 format option: -mfp16-format=%s", - target_fp16_format_name); - } - else - arm_fp16_format = ARM_FP16_FORMAT_NONE; - - if (target_abi_name) - { - for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++) - { - if (streq (arm_all_abis[i].name, target_abi_name)) - { - arm_abi = arm_all_abis[i].abi_type; - break; - } - } - if (i == ARRAY_SIZE (arm_all_abis)) - error ("invalid ABI option: -mabi=%s", target_abi_name); - } - else - arm_abi = ARM_DEFAULT_ABI; - /* Make sure that the processor choice does not conflict with any of the other command line choices. */ if (TARGET_ARM && !(insn_flags & FL_NOTM)) @@ -1607,19 +1490,11 @@ arm_option_override (void) if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT) error ("iwmmxt abi requires an iwmmxt capable cpu"); - if (target_fpu_name == NULL && target_fpe_name != NULL) + if (!global_options_set.x_arm_fpu_index) { - if (streq (target_fpe_name, "2")) - target_fpu_name = "fpe2"; - else if (streq (target_fpe_name, "3")) - target_fpu_name = "fpe3"; - else - error ("invalid floating point emulation option: -mfpe=%s", - target_fpe_name); - } + const char *target_fpu_name; + bool ok; - if (target_fpu_name == NULL) - { #ifdef FPUTYPE_DEFAULT target_fpu_name = FPUTYPE_DEFAULT; #else @@ -1628,23 +1503,13 @@ arm_option_override (void) else target_fpu_name = "fpe2"; #endif - } - arm_fpu_desc = NULL; - for (i = 0; i < ARRAY_SIZE (all_fpus); i++) - { - if (streq (all_fpus[i].name, target_fpu_name)) - { - arm_fpu_desc = &all_fpus[i]; - break; - } + ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &arm_fpu_index, + CL_TARGET); + gcc_assert (ok); } - if (!arm_fpu_desc) - { - error ("invalid floating point option: -mfpu=%s", target_fpu_name); - return; - } + arm_fpu_desc = &all_fpus[arm_fpu_index]; switch (arm_fpu_desc->model) { @@ -1669,24 +1534,6 @@ arm_option_override (void) gcc_unreachable(); } - if (target_float_abi_name != NULL) - { - /* The user specified a FP ABI. */ - for (i = 0; i < ARRAY_SIZE (all_float_abis); i++) - { - if (streq (all_float_abis[i].name, target_float_abi_name)) - { - arm_float_abi = all_float_abis[i].abi_type; - break; - } - } - if (i == ARRAY_SIZE (all_float_abis)) - error ("invalid floating point abi: -mfloat-abi=%s", - target_float_abi_name); - } - else - arm_float_abi = TARGET_DEFAULT_FLOAT_ABI; - if (TARGET_AAPCS_BASED && (arm_fpu_desc->model == ARM_FP_MODEL_FPA)) error ("FPA is unsupported in the AAPCS"); @@ -1747,18 +1594,6 @@ arm_option_override (void) && (tune_flags & FL_MODE32) == 0) flag_schedule_insns = flag_schedule_insns_after_reload = 0; - if (target_thread_switch) - { - if (strcmp (target_thread_switch, "soft") == 0) - target_thread_pointer = TP_SOFT; - else if (strcmp (target_thread_switch, "auto") == 0) - target_thread_pointer = TP_AUTO; - else if (strcmp (target_thread_switch, "cp15") == 0) - target_thread_pointer = TP_CP15; - else - error ("invalid thread pointer option: -mtp=%s", target_thread_switch); - } - /* Use the cp15 method if it is available. */ if (target_thread_pointer == TP_AUTO) { @@ -1772,19 +1607,25 @@ arm_option_override (void) error ("can not use -mtp=cp15 with 16-bit Thumb"); /* Override the default structure alignment for AAPCS ABI. */ - if (TARGET_AAPCS_BASED) - arm_structure_size_boundary = 8; - - if (structure_size_string != NULL) + if (!global_options_set.x_arm_structure_size_boundary) { - int size = strtol (structure_size_string, NULL, 0); - - if (size == 8 || size == 32 - || (ARM_DOUBLEWORD_ALIGN && size == 64)) - arm_structure_size_boundary = size; - else - warning (0, "structure size boundary can only be set to %s", - ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32"); + if (TARGET_AAPCS_BASED) + arm_structure_size_boundary = 8; + } + else + { + if (arm_structure_size_boundary != 8 + && arm_structure_size_boundary != 32 + && !(ARM_DOUBLEWORD_ALIGN && arm_structure_size_boundary == 64)) + { + if (ARM_DOUBLEWORD_ALIGN) + warning (0, + "structure size boundary can only be set to 8, 32 or 64"); + else + warning (0, "structure size boundary can only be set to 8 or 32"); + arm_structure_size_boundary + = (TARGET_AAPCS_BASED ? 8 : DEFAULT_STRUCTURE_SIZE_BOUNDARY); + } } if (!TARGET_ARM && TARGET_VXWORKS_RTP && flag_pic) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 43323942a44..86d842ddf4a 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -349,59 +349,17 @@ extern const struct arm_fpu_desc /* Which floating point hardware to schedule for. */ extern int arm_fpu_attr; -enum float_abi_type -{ - ARM_FLOAT_ABI_SOFT, - ARM_FLOAT_ABI_SOFTFP, - ARM_FLOAT_ABI_HARD -}; - -extern enum float_abi_type arm_float_abi; - #ifndef TARGET_DEFAULT_FLOAT_ABI #define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT #endif -/* Which __fp16 format to use. - The enumeration values correspond to the numbering for the - Tag_ABI_FP_16bit_format attribute. - */ -enum arm_fp16_format_type -{ - ARM_FP16_FORMAT_NONE = 0, - ARM_FP16_FORMAT_IEEE = 1, - ARM_FP16_FORMAT_ALTERNATIVE = 2 -}; - -extern enum arm_fp16_format_type arm_fp16_format; #define LARGEST_EXPONENT_IS_NORMAL(bits) \ ((bits) == 16 && arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE) -/* Which ABI to use. */ -enum arm_abi_type -{ - ARM_ABI_APCS, - ARM_ABI_ATPCS, - ARM_ABI_AAPCS, - ARM_ABI_IWMMXT, - ARM_ABI_AAPCS_LINUX -}; - -extern enum arm_abi_type arm_abi; - #ifndef ARM_DEFAULT_ABI #define ARM_DEFAULT_ABI ARM_ABI_APCS #endif -/* Which thread pointer access sequence to use. */ -enum arm_tp_type { - TP_AUTO, - TP_SOFT, - TP_CP15 -}; - -extern enum arm_tp_type target_thread_pointer; - /* Nonzero if this chip supports the ARM Architecture 3M extensions. */ extern int arm_arch3m; @@ -614,7 +572,6 @@ extern int arm_arch_hwdiv; 0020D) page 2-20 says "Structures are aligned on word boundaries". The AAPCS specifies a value of 8. */ #define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary -extern int arm_structure_size_boundary; /* This is the value used to initialize arm_structure_size_boundary. If a particular arm target wants to change the default value it should change diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt index 89c8cbd47d4..c45bc774bdc 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -22,9 +22,28 @@ HeaderInclude config/arm/arm-opts.h mabi= -Target RejectNegative Joined Var(target_abi_name) +Target RejectNegative Joined Enum(arm_abi_type) Var(arm_abi) Init(ARM_DEFAULT_ABI) Specify an ABI +Enum +Name(arm_abi_type) Type(enum arm_abi_type) +Known ARM ABIs (for use with the -mabi= option): + +EnumValue +Enum(arm_abi_type) String(apcs-gnu) Value(ARM_ABI_APCS) + +EnumValue +Enum(arm_abi_type) String(atpcs) Value(ARM_ABI_ATPCS) + +EnumValue +Enum(arm_abi_type) String(aapcs) Value(ARM_ABI_AAPCS) + +EnumValue +Enum(arm_abi_type) String(iwmmxt) Value(ARM_ABI_IWMMXT) + +EnumValue +Enum(arm_abi_type) String(aapcs-linux) Value(ARM_ABI_AAPCS_LINUX) + mabort-on-noreturn Target Report Mask(ABORT_NORETURN) Generate a call to abort if a noreturn function returns @@ -76,25 +95,57 @@ Target RejectNegative Joined Enum(processor_type) Var(arm_cpu_option) Init(arm_n Specify the name of the target CPU mfloat-abi= -Target RejectNegative Joined Var(target_float_abi_name) +Target RejectNegative Joined Enum(float_abi_type) Var(arm_float_abi) Init(TARGET_DEFAULT_FLOAT_ABI) Specify if floating point hardware should be used -mfp= -Target RejectNegative Joined Undocumented Var(target_fpe_name) +Enum +Name(float_abi_type) Type(enum float_abi_type) +Known floating-point ABIs (for use with the -mfloat-abi= option): + +EnumValue +Enum(float_abi_type) String(soft) Value(ARM_FLOAT_ABI_SOFT) + +EnumValue +Enum(float_abi_type) String(softfp) Value(ARM_FLOAT_ABI_SOFTFP) + +EnumValue +Enum(float_abi_type) String(hard) Value(ARM_FLOAT_ABI_HARD) + +mfp=2 +Target RejectNegative Undocumented Alias(mfpu=, fpe2) + +mfp=3 +Target RejectNegative Undocumented Alias(mfpu=, fpe3) mfp16-format= -Target RejectNegative Joined Var(target_fp16_format_name) +Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_NONE) Specify the __fp16 floating-point format +Enum +Name(arm_fp16_format_type) Type(enum arm_fp16_format_type) +Known __fp16 formats (for use with the -mfp16-format= option): + +EnumValue +Enum(arm_fp16_format_type) String(none) Value(ARM_FP16_FORMAT_NONE) + +EnumValue +Enum(arm_fp16_format_type) String(ieee) Value(ARM_FP16_FORMAT_IEEE) + +EnumValue +Enum(arm_fp16_format_type) String(alternative) Value(ARM_FP16_FORMAT_ALTERNATIVE) + ;; Now ignored. mfpe Target RejectNegative Mask(FPE) Undocumented -mfpe= -Target RejectNegative Joined Undocumented Var(target_fpe_name) +mfpe=2 +Target RejectNegative Undocumented Alias(mfpu=, fpe2) + +mfpe=3 +Target RejectNegative Undocumented Alias(mfpu=, fpe3) mfpu= -Target RejectNegative Joined Var(target_fpu_name) +Target RejectNegative Joined Enum(arm_fpu) Var(arm_fpu_index) Specify the name of the target floating point hardware/format mhard-float @@ -128,7 +179,7 @@ msoft-float Target RejectNegative Alias(mfloat-abi=, soft) Undocumented mstructure-size-boundary= -Target RejectNegative Joined Var(structure_size_string) +Target RejectNegative Joined UInteger Var(arm_structure_size_boundary) Init(DEFAULT_STRUCTURE_SIZE_BOUNDARY) Specify the minimum bit alignment of structures mthumb @@ -140,9 +191,22 @@ Target Report Mask(INTERWORK) Support calls between Thumb and ARM instruction sets mtp= -Target RejectNegative Joined Var(target_thread_switch) +Target RejectNegative Joined Enum(arm_tp_type) Var(target_thread_pointer) Init(TP_AUTO) Specify how to access the thread pointer +Enum +Name(arm_tp_type) Type(enum arm_tp_type) +Valid arguments to -mtp=: + +EnumValue +Enum(arm_tp_type) String(soft) Value(TP_SOFT) + +EnumValue +Enum(arm_tp_type) String(auto) Value(TP_AUTO) + +EnumValue +Enum(arm_tp_type) String(cp15) Value(TP_CP15) + mtpcs-frame Target Report Mask(TPCS_FRAME) Thumb: Generate (non-leaf) stack frames even if not needed diff --git a/gcc/config/arm/genopt.sh b/gcc/config/arm/genopt.sh index 28cee6caabe..6b31896d8f5 100755 --- a/gcc/config/arm/genopt.sh +++ b/gcc/config/arm/genopt.sh @@ -20,7 +20,8 @@ cat <<EOF ; -*- buffer-read-only: t -*- -; Generated automatically by genopt.sh from arm-cores.def and arm-arches.def. +; Generated automatically by genopt.sh from arm-cores.def, arm-arches.def +; and arm-fpus.def. ; Copyright (C) 2011 Free Software Foundation, Inc. ; @@ -73,3 +74,22 @@ awk -F'[(, ]+' 'BEGIN { print "" value++ }' $1/arm-arches.def + +cat <<EOF +Enum +Name(arm_fpu) Type(int) +Known ARM FPUs (for use with the -mfpu= option): + +EOF + +awk -F'[(, ]+' 'BEGIN { + value = 0 +} +/^ARM_FPU/ { + name = $2 + gsub("\"", "", name) + print "EnumValue" + print "Enum(arm_fpu) String(" name ") Value(" value ")" + print "" + value++ +}' $1/arm-fpus.def diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm index 18a548a3f74..826ec0af5c2 100644 --- a/gcc/config/arm/t-arm +++ b/gcc/config/arm/t-arm @@ -52,7 +52,8 @@ $(srcdir)/config/arm/arm-tune.md: $(srcdir)/config/arm/gentune.sh \ $(srcdir)/config/arm/arm-tune.md $(srcdir)/config/arm/arm-tables.opt: $(srcdir)/config/arm/genopt.sh \ - $(srcdir)/config/arm/arm-cores.def $(srcdir)/config/arm/arm-arches.def + $(srcdir)/config/arm/arm-cores.def $(srcdir)/config/arm/arm-arches.def \ + $(srcdir)/config/arm/arm-fpus.def $(SHELL) $(srcdir)/config/arm/genopt.sh $(srcdir)/config/arm > \ $(srcdir)/config/arm/arm-tables.opt @@ -64,7 +65,7 @@ arm.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(GGC_H) except.h $(C_PRAGMA_H) $(INTEGRATE_H) $(TM_P_H) \ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) $(srcdir)/config/arm/arm-cores.def \ - $(srcdir)/config/arm/arm-arches.def + $(srcdir)/config/arm/arm-arches.def $(srcdir)/config/arm/arm-fpus.def arm-c.o: $(srcdir)/config/arm/arm-c.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index ac4b3182d81..c8c363ad948 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -1796,6 +1796,20 @@ avr_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, cfun->machine->sibcall_fails = 1; } + /* Test if all registers needed by the ABI are actually available. If the + user has fixed a GPR needed to pass an argument, an (implicit) function + call would clobber that fixed register. See PR45099 for an example. */ + + if (cum->regno >= 0) + { + int regno; + + for (regno = cum->regno; regno < cum->regno + bytes; regno++) + if (fixed_regs[regno]) + error ("Register %s is needed to pass a parameter but is fixed", + reg_names[regno]); + } + if (cum->nregs <= 0) { cum->nregs = 0; diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 1ab30332bdb..efe6bb6914f 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -3388,3 +3388,42 @@ clr __zero_reg__" [(set_attr "length" "3") (set_attr "cc" "clobber")]) + + +;; Some combine patterns that try to fix bad code when a value is composed +;; from byte parts like in PR27663. +;; The patterns give some release but the code still is not optimal, +;; in particular when subreg lowering (-fsplit-wide-types) is turned on. +;; That switch obfuscates things here and in many other places. + +(define_insn_and_split "*ior<mode>qi.byte0" + [(set (match_operand:HISI 0 "register_operand" "=r") + (ior:HISI + (zero_extend:HISI (match_operand:QI 1 "register_operand" "r")) + (match_operand:HISI 2 "register_operand" "0")))] + "" + "#" + "reload_completed" + [(set (match_dup 3) + (ior:QI (match_dup 3) + (match_dup 1)))] + { + operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0); + }) + +(define_insn_and_split "*ior<mode>qi.byte1-3" + [(set (match_operand:HISI 0 "register_operand" "=r") + (ior:HISI + (ashift:HISI (zero_extend:HISI (match_operand:QI 1 "register_operand" "r")) + (match_operand:QI 2 "const_8_16_24_operand" "n")) + (match_operand:HISI 3 "register_operand" "0")))] + "INTVAL(operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" + "#" + "&& reload_completed" + [(set (match_dup 4) + (ior:QI (match_dup 4) + (match_dup 1)))] + { + int byteno = INTVAL(operands[2]) / BITS_PER_UNIT; + operands[4] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, byteno); + }) diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md index 9a3473bf88f..a7cc2ba052f 100755 --- a/gcc/config/avr/predicates.md +++ b/gcc/config/avr/predicates.md @@ -138,3 +138,10 @@ (define_predicate "pseudo_register_operand" (and (match_code "reg") (match_test "!HARD_REGISTER_P (op)"))) + +;; Return true if OP is a constant integer that is either +;; 8 or 16 or 24. +(define_predicate "const_8_16_24_operand" + (and (match_code "const_int") + (match_test "8 == INTVAL(op) || 16 == INTVAL(op) || 24 == INTVAL(op)"))) + diff --git a/gcc/config/bfin/bfin-opts.h b/gcc/config/bfin/bfin-opts.h index d0780a6b52c..329fa1e625c 100644 --- a/gcc/config/bfin/bfin-opts.h +++ b/gcc/config/bfin/bfin-opts.h @@ -53,7 +53,8 @@ typedef enum bfin_cpu_type BFIN_CPU_BF548M, BFIN_CPU_BF549, BFIN_CPU_BF549M, - BFIN_CPU_BF561 + BFIN_CPU_BF561, + BFIN_CPU_BF592 } bfin_cpu_t; #endif diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 2d4e33e5cf4..4f371fd928f 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -350,6 +350,11 @@ static const struct bfin_cpu bfin_cpus[] = | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074}, + {"bf592", BFIN_CPU_BF592, 0x0001, + WA_SPECULATIVE_LOADS | WA_05000074}, + {"bf592", BFIN_CPU_BF592, 0x0000, + WA_SPECULATIVE_LOADS | WA_05000074}, + {NULL, BFIN_CPU_UNKNOWN, 0, 0} }; diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 0d83ad82126..4f21a1c8a32 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -140,6 +140,10 @@ case BFIN_CPU_BF561: \ builtin_define ("__ADSPBF561__"); \ break; \ + case BFIN_CPU_BF592: \ + builtin_define ("__ADSPBF592__"); \ + builtin_define ("__ADSPBF59x__"); \ + break; \ } \ \ if (bfin_si_revision != -1) \ diff --git a/gcc/config/bfin/elf.h b/gcc/config/bfin/elf.h index 975212faa23..14e209aa494 100644 --- a/gcc/config/bfin/elf.h +++ b/gcc/config/bfin/elf.h @@ -51,6 +51,7 @@ crti%O%s crtbegin%O%s crtlibid%O%s" %{mmulticore:%{mcorea:-T bf561a.ld%s}} \ %{mmulticore:%{mcoreb:-T bf561b.ld%s}} \ %{mmulticore:%{!mcorea:%{!mcoreb:-T bf561m.ld%s}}}} \ + %{mcpu=bf592*:-T bf592.ld%s} \ %{!mcpu=*:%eno processor type specified for linking} \ %{!mcpu=bf561*:-T bfin-common-sc.ld%s} \ %{mcpu=bf561*:%{!mmulticore:-T bfin-common-sc.ld%s} \ diff --git a/gcc/config/bfin/t-bfin-elf b/gcc/config/bfin/t-bfin-elf index da242a08a21..867a71dce77 100644 --- a/gcc/config/bfin/t-bfin-elf +++ b/gcc/config/bfin/t-bfin-elf @@ -58,6 +58,7 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none +MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none MULTILIB_EXCEPTIONS=mleaf-id-shared-library* MULTILIB_EXCEPTIONS+=mcpu=bf532-none/mleaf-id-shared-library* diff --git a/gcc/config/bfin/t-bfin-linux b/gcc/config/bfin/t-bfin-linux index daa1e059ce4..65d8f7a97f3 100644 --- a/gcc/config/bfin/t-bfin-linux +++ b/gcc/config/bfin/t-bfin-linux @@ -57,6 +57,7 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none +MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none SHLIB_MAPFILES=$(srcdir)/config/bfin/libgcc-bfin.ver diff --git a/gcc/config/bfin/t-bfin-uclinux b/gcc/config/bfin/t-bfin-uclinux index 0be258f2f11..9990c0d4f2b 100644 --- a/gcc/config/bfin/t-bfin-uclinux +++ b/gcc/config/bfin/t-bfin-uclinux @@ -58,6 +58,7 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none +MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none MULTILIB_EXCEPTIONS=mleaf-id-shared-library* MULTILIB_EXCEPTIONS+=mcpu=bf532-none/mleaf-id-shared-library* diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 89722bb92da..458364bca4a 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -19,7 +19,7 @@ ;;; Unused letters: ;;; B H T W -;;; h jk vw z +;;; h jk vw ;; Integer register constraints. ;; It is not necessary to define 'r' here. @@ -90,6 +90,8 @@ ;; 2 SSE2 enabled ;; i SSE2 inter-unit moves enabled ;; m MMX inter-unit moves enabled +;; d Integer register when integer DFmode moves are enabled +;; x Integer register when integer XFmode moves are enabled (define_register_constraint "Yz" "TARGET_SSE ? SSE_FIRST_REG : NO_REGS" "First SSE register (@code{%xmm0}).") @@ -105,6 +107,18 @@ "TARGET_MMX && TARGET_INTER_UNIT_MOVES ? MMX_REGS : NO_REGS" "@internal Any MMX register, when inter-unit moves are enabled.") +(define_register_constraint "Yd" + "TARGET_INTEGER_DFMODE_MOVES ? GENERAL_REGS : NO_REGS" + "@internal Any integer register when integer DFmode moves are enabled.") + +(define_register_constraint "Yx" + "optimize_function_for_speed_p (cfun) ? GENERAL_REGS : NO_REGS" + "@internal Any integer register when integer XFmode moves are enabled.") + +(define_constraint "z" + "@internal Constant call address operand." + (match_operand 0 "constant_call_address_operand")) + ;; Integer constant constraints. (define_constraint "I" "Integer constant in the range 0 @dots{} 31, for 32-bit shifts." @@ -149,7 +163,7 @@ (define_constraint "G" "Standard 80387 floating point constant." (and (match_code "const_double") - (match_test "standard_80387_constant_p (op)"))) + (match_test "standard_80387_constant_p (op) > 0"))) ;; This can theoretically be any mode's CONST0_RTX. (define_constraint "C" diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index 14973513334..56765484364 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -340,14 +340,14 @@ ix86_pragma_target_parse (tree args, tree pop_target) ix86_target_macros_internal (prev_isa & diff_isa, prev_arch, prev_tune, - (enum fpmath_unit) prev_opt->fpmath, + (enum fpmath_unit) prev_opt->x_ix86_fpmath, cpp_undef); /* Define all of the macros for new options that were just turned on. */ ix86_target_macros_internal (cur_isa & diff_isa, cur_arch, cur_tune, - (enum fpmath_unit) cur_opt->fpmath, + (enum fpmath_unit) cur_opt->x_ix86_fpmath, cpp_define); return true; diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h new file mode 100644 index 00000000000..3cc2253c3c2 --- /dev/null +++ b/gcc/config/i386/i386-opts.h @@ -0,0 +1,85 @@ +/* Definitions for option handling for IA-32. + Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +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 I386_OPTS_H +#define I386_OPTS_H + +/* Algorithm to expand string function with. */ +enum stringop_alg +{ + no_stringop, + libcall, + rep_prefix_1_byte, + rep_prefix_4_byte, + rep_prefix_8_byte, + loop_1_byte, + loop, + unrolled_loop +}; + +/* Available call abi. */ +enum calling_abi +{ + SYSV_ABI = 0, + MS_ABI = 1 +}; + +enum fpmath_unit +{ + FPMATH_387 = 1, + FPMATH_SSE = 2 +}; + +enum tls_dialect +{ + TLS_DIALECT_GNU, + TLS_DIALECT_GNU2, + TLS_DIALECT_SUN +}; + +enum cmodel { + CM_32, /* The traditional 32-bit ABI. */ + CM_SMALL, /* Assumes all code and data fits in the low 31 bits. */ + CM_KERNEL, /* Assumes all code and data fits in the high 31 bits. */ + CM_MEDIUM, /* Assumes code fits in the low 31 bits; data unlimited. */ + CM_LARGE, /* No assumptions. */ + CM_SMALL_PIC, /* Assumes code+data+got/plt fits in a 31 bit region. */ + CM_MEDIUM_PIC,/* Assumes code+got/plt fits in a 31 bit region. */ + CM_LARGE_PIC /* No assumptions. */ +}; + +enum asm_dialect { + ASM_ATT, + ASM_INTEL +}; + +enum ix86_veclibabi { + ix86_veclibabi_type_none, + ix86_veclibabi_type_svml, + ix86_veclibabi_type_acml +}; + +#endif diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index ccba8484bdc..5643153ac39 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -67,8 +67,8 @@ extern void split_double_mode (enum machine_mode, rtx[], int, rtx[], rtx[]); extern const char *output_set_got (rtx, rtx); extern const char *output_387_binary_op (rtx, rtx*); extern const char *output_387_reg_move (rtx, rtx*); -extern const char *output_fix_trunc (rtx, rtx*, int); -extern const char *output_fp_compare (rtx, rtx*, int, int); +extern const char *output_fix_trunc (rtx, rtx*, bool); +extern const char *output_fp_compare (rtx, rtx*, bool, bool); extern const char *output_adjust_stack_and_probe (rtx); extern const char *output_probe_stack_range (rtx, rtx); @@ -114,7 +114,7 @@ extern bool ix86_expand_fp_vcond (rtx[]); extern bool ix86_expand_int_vcond (rtx[]); extern void ix86_expand_sse_unpack (rtx[], bool, bool); extern bool ix86_expand_int_addcc (rtx[]); -extern rtx ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int); +extern rtx ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool); extern void ix86_split_call_vzeroupper (rtx, rtx); extern void x86_initialize_trampoline (rtx, rtx, rtx); extern rtx ix86_zero_extend_to_Pmode (rtx); @@ -127,9 +127,9 @@ extern bool ix86_check_movabs (rtx, int); extern void ix86_split_idivmod (enum machine_mode, rtx[], bool); extern rtx assign_386_stack_local (enum machine_mode, enum ix86_stack_slot); -extern int ix86_attr_length_immediate_default (rtx, int); +extern int ix86_attr_length_immediate_default (rtx, bool); extern int ix86_attr_length_address_default (rtx); -extern int ix86_attr_length_vex_default (rtx, int, int); +extern int ix86_attr_length_vex_default (rtx, bool, bool); extern enum machine_mode ix86_fp_compare_mode (enum rtx_code); @@ -193,7 +193,6 @@ extern unsigned int ix86_get_callcvt (const_tree); #endif -extern rtx ix86_tls_get_addr (void); extern rtx ix86_tls_module_base (void); extern void ix86_expand_vector_init (bool, rtx, rtx); @@ -271,7 +270,7 @@ extern int asm_preferred_eh_data_format (int, int); extern enum attr_cpu ix86_schedule; #endif -extern const char * ix86_output_call_insn (rtx insn, rtx call_op, int addr_op); +extern const char * ix86_output_call_insn (rtx insn, rtx call_op); #ifdef RTX_CODE /* Target data for multipass lookahead scheduling. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index afba1a7049d..0709be819fd 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see #include "sbitmap.h" #include "fibheap.h" #include "opts.h" +#include "diagnostic.h" enum upper_128bits_state { @@ -2120,8 +2121,6 @@ static const unsigned int x86_arch_always_fancy_math_387 = m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2I7 | m_GENERIC; -static enum stringop_alg stringop_alg = no_stringop; - /* In case the average insn count for single function invocation is lower than this constant, emit fast (but longer) prologue and epilogue code. */ @@ -2327,16 +2326,6 @@ struct ix86_frame bool save_regs_using_mov; }; -/* Code model option. */ -enum cmodel ix86_cmodel; -/* Asm dialect. */ -enum asm_dialect ix86_asm_dialect = ASM_ATT; -/* TLS dialects. */ -enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU; - -/* Which unit we are generating floating point math for. */ -enum fpmath_unit ix86_fpmath; - /* Which cpu are we scheduling for. */ enum attr_cpu ix86_schedule; @@ -2349,9 +2338,6 @@ enum processor_type ix86_arch; /* true if sse prefetch instruction is not NOOP. */ int x86_prefetch_sse; -/* ix86_regparm_string as a number */ -static int ix86_regparm; - /* -mstackrealign option */ static const char ix86_force_align_arg_pointer_string[] = "force_align_arg_pointer"; @@ -2380,21 +2366,10 @@ static unsigned int ix86_default_incoming_stack_boundary; /* Alignment for incoming stack boundary in bits. */ unsigned int ix86_incoming_stack_boundary; -/* The abi used by target. */ -enum calling_abi ix86_abi; - -/* Values 1-5: see jump.c */ -int ix86_branch_cost; - /* Calling abi specific va_list type nodes. */ static GTY(()) tree sysv_va_list_type_node; static GTY(()) tree ms_va_list_type_node; -/* Variables which are this size or smaller are put in the data/bss - or ldata/lbss sections. */ - -int ix86_section_threshold = 65536; - /* Prefix built by ASM_GENERATE_INTERNAL_LABEL. */ char internal_label_prefix[16]; int internal_label_prefix_len; @@ -2452,19 +2427,19 @@ enum ix86_function_specific_strings { IX86_FUNCTION_SPECIFIC_ARCH, IX86_FUNCTION_SPECIFIC_TUNE, - IX86_FUNCTION_SPECIFIC_FPMATH, IX86_FUNCTION_SPECIFIC_MAX }; static char *ix86_target_string (int, int, const char *, const char *, - const char *, bool); + enum fpmath_unit, bool); static void ix86_debug_options (void) ATTRIBUTE_UNUSED; static void ix86_function_specific_save (struct cl_target_option *); static void ix86_function_specific_restore (struct cl_target_option *); static void ix86_function_specific_print (FILE *, int, struct cl_target_option *); static bool ix86_valid_target_attribute_p (tree, tree, tree, int); -static bool ix86_valid_target_attribute_inner_p (tree, char *[]); +static bool ix86_valid_target_attribute_inner_p (tree, char *[], + struct gcc_options *); static bool ix86_can_inline_p (tree, tree); static void ix86_set_current_function (tree); static unsigned int ix86_minimum_incoming_stack_boundary (bool); @@ -2688,7 +2663,7 @@ static bool ix86_handle_option (struct gcc_options *opts, struct gcc_options *opts_set ATTRIBUTE_UNUSED, const struct cl_decoded_option *decoded, - location_t loc ATTRIBUTE_UNUSED) + location_t loc) { size_t code = decoded->opt_index; int value = decoded->value; @@ -3059,6 +3034,45 @@ ix86_handle_option (struct gcc_options *opts, } return true; + /* Comes from final.c -- no real reason to change it. */ +#define MAX_CODE_ALIGN 16 + + case OPT_malign_loops_: + warning_at (loc, 0, "-malign-loops is obsolete, use -falign-loops"); + if (value > MAX_CODE_ALIGN) + error_at (loc, "-malign-loops=%d is not between 0 and %d", + value, MAX_CODE_ALIGN); + else + opts->x_align_loops = 1 << value; + return true; + + case OPT_malign_jumps_: + warning_at (loc, 0, "-malign-jumps is obsolete, use -falign-jumps"); + if (value > MAX_CODE_ALIGN) + error_at (loc, "-malign-jumps=%d is not between 0 and %d", + value, MAX_CODE_ALIGN); + else + opts->x_align_jumps = 1 << value; + return true; + + case OPT_malign_functions_: + warning_at (loc, 0, + "-malign-functions is obsolete, use -falign-functions"); + if (value > MAX_CODE_ALIGN) + error_at (loc, "-malign-functions=%d is not between 0 and %d", + value, MAX_CODE_ALIGN); + else + opts->x_align_functions = 1 << value; + return true; + + case OPT_mbranch_cost_: + if (value > 5) + { + error_at (loc, "-mbranch-cost=%d is not between 0 and 5", value); + opts->x_ix86_branch_cost = 5; + } + return true; + default: return true; } @@ -3069,7 +3083,7 @@ ix86_handle_option (struct gcc_options *opts, static char * ix86_target_string (int isa, int flags, const char *arch, const char *tune, - const char *fpmath, bool add_nl_p) + enum fpmath_unit fpmath, bool add_nl_p) { struct ix86_target_opts { @@ -3203,7 +3217,23 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune, if (fpmath) { opts[num][0] = "-mfpmath="; - opts[num++][1] = fpmath; + switch ((int) fpmath) + { + case FPMATH_387: + opts[num++][1] = "387"; + break; + + case FPMATH_SSE: + opts[num++][1] = "sse"; + break; + + case FPMATH_387 | FPMATH_SSE: + opts[num++][1] = "sse+387"; + break; + + default: + gcc_unreachable (); + } } /* Any options? */ @@ -3278,7 +3308,7 @@ ix86_debug_options (void) { char *opts = ix86_target_string (ix86_isa_flags, target_flags, ix86_arch_string, ix86_tune_string, - ix86_fpmath_string, true); + ix86_fpmath, true); if (opts) { @@ -3305,9 +3335,6 @@ ix86_option_override_internal (bool main_args_p) const char *suffix; const char *sw; - /* Comes from final.c -- no real reason to change it. */ -#define MAX_CODE_ALIGN 16 - enum pta_flags { PTA_SSE = 1 << 0, @@ -3530,27 +3557,11 @@ ix86_option_override_internal (bool main_args_p) } } - if (ix86_stringop_string) - { - if (!strcmp (ix86_stringop_string, "rep_byte")) - stringop_alg = rep_prefix_1_byte; - else if (!strcmp (ix86_stringop_string, "libcall")) - stringop_alg = libcall; - else if (!strcmp (ix86_stringop_string, "rep_4byte")) - stringop_alg = rep_prefix_4_byte; - else if (!strcmp (ix86_stringop_string, "rep_8byte") - && TARGET_64BIT) - /* rep; movq isn't available in 32-bit code. */ - stringop_alg = rep_prefix_8_byte; - else if (!strcmp (ix86_stringop_string, "byte_loop")) - stringop_alg = loop_1_byte; - else if (!strcmp (ix86_stringop_string, "loop")) - stringop_alg = loop; - else if (!strcmp (ix86_stringop_string, "unrolled_loop")) - stringop_alg = unrolled_loop; - else - error ("bad value (%s) for %sstringop-strategy=%s %s", - ix86_stringop_string, prefix, suffix, sw); + if (ix86_stringop_alg == rep_prefix_8_byte && !TARGET_64BIT) + { + /* rep; movq isn't available in 32-bit code. */ + error ("-mstringop-strategy=rep_8byte not supported for 32-bit code"); + ix86_stringop_alg = no_stringop; } if (!ix86_arch_string) @@ -3558,37 +3569,62 @@ ix86_option_override_internal (bool main_args_p) else ix86_arch_specified = 1; - /* Validate -mabi= value. */ - if (ix86_abi_string) - { - if (strcmp (ix86_abi_string, "sysv") == 0) - ix86_abi = SYSV_ABI; - else if (strcmp (ix86_abi_string, "ms") == 0) - ix86_abi = MS_ABI; - else - error ("unknown ABI (%s) for %sabi=%s %s", - ix86_abi_string, prefix, suffix, sw); - } - else + if (!global_options_set.x_ix86_abi) ix86_abi = DEFAULT_ABI; - if (ix86_cmodel_string != 0) + if (global_options_set.x_ix86_cmodel) { - if (!strcmp (ix86_cmodel_string, "small")) - ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; - else if (!strcmp (ix86_cmodel_string, "medium")) - ix86_cmodel = flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM; - else if (!strcmp (ix86_cmodel_string, "large")) - ix86_cmodel = flag_pic ? CM_LARGE_PIC : CM_LARGE; - else if (flag_pic) - error ("code model %s does not support PIC mode", ix86_cmodel_string); - else if (!strcmp (ix86_cmodel_string, "32")) - ix86_cmodel = CM_32; - else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic) - ix86_cmodel = CM_KERNEL; - else - error ("bad value (%s) for %scmodel=%s %s", - ix86_cmodel_string, prefix, suffix, sw); + switch (ix86_cmodel) + { + case CM_SMALL: + case CM_SMALL_PIC: + if (flag_pic) + ix86_cmodel = CM_SMALL_PIC; + if (!TARGET_64BIT) + error ("code model %qs not supported in the %s bit mode", + "small", "32"); + break; + + case CM_MEDIUM: + case CM_MEDIUM_PIC: + if (flag_pic) + ix86_cmodel = CM_MEDIUM_PIC; + if (!TARGET_64BIT) + error ("code model %qs not supported in the %s bit mode", + "medium", "32"); + break; + + case CM_LARGE: + case CM_LARGE_PIC: + if (flag_pic) + ix86_cmodel = CM_LARGE_PIC; + if (!TARGET_64BIT) + error ("code model %qs not supported in the %s bit mode", + "large", "32"); + break; + + case CM_32: + if (flag_pic) + error ("code model %s does not support PIC mode", "32"); + if (TARGET_64BIT) + error ("code model %qs not supported in the %s bit mode", + "32", "64"); + break; + + case CM_KERNEL: + if (flag_pic) + { + error ("code model %s does not support PIC mode", "kernel"); + ix86_cmodel = CM_32; + } + if (!TARGET_64BIT) + error ("code model %qs not supported in the %s bit mode", + "kernel", "32"); + break; + + default: + gcc_unreachable (); + } } else { @@ -3603,20 +3639,11 @@ ix86_option_override_internal (bool main_args_p) else ix86_cmodel = CM_32; } - if (ix86_asm_string != 0) + if (TARGET_MACHO && ix86_asm_dialect == ASM_INTEL) { - if (! TARGET_MACHO - && !strcmp (ix86_asm_string, "intel")) - ix86_asm_dialect = ASM_INTEL; - else if (!strcmp (ix86_asm_string, "att")) - ix86_asm_dialect = ASM_ATT; - else - error ("bad value (%s) for %sasm=%s %s", - ix86_asm_string, prefix, suffix, sw); + error ("-masm=intel not supported in this configuration"); + ix86_asm_dialect = ASM_ATT; } - if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32)) - error ("code model %qs not supported in the %s bit mode", - ix86_cmodel_string, TARGET_64BIT ? "64" : "32"); if ((TARGET_64BIT != 0) != ((ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0)) sorry ("%i-bit mode not compiled in", (ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32); @@ -3836,67 +3863,19 @@ ix86_option_override_internal (bool main_args_p) init_machine_status = ix86_init_machine_status; /* Validate -mregparm= value. */ - if (ix86_regparm_string) + if (global_options_set.x_ix86_regparm) { if (TARGET_64BIT) - warning (0, "%sregparm%s is ignored in 64-bit mode", prefix, suffix); - i = atoi (ix86_regparm_string); - if (i < 0 || i > REGPARM_MAX) - error ("%sregparm=%d%s is not between 0 and %d", - prefix, i, suffix, REGPARM_MAX); - else - ix86_regparm = i; - } - if (TARGET_64BIT) - ix86_regparm = REGPARM_MAX; - - /* If the user has provided any of the -malign-* options, - warn and use that value only if -falign-* is not set. - Remove this code in GCC 3.2 or later. */ - if (ix86_align_loops_string) - { - warning (0, "%salign-loops%s is obsolete, use -falign-loops%s", - prefix, suffix, suffix); - if (align_loops == 0) - { - i = atoi (ix86_align_loops_string); - if (i < 0 || i > MAX_CODE_ALIGN) - error ("%salign-loops=%d%s is not between 0 and %d", - prefix, i, suffix, MAX_CODE_ALIGN); - else - align_loops = 1 << i; - } - } - - if (ix86_align_jumps_string) - { - warning (0, "%salign-jumps%s is obsolete, use -falign-jumps%s", - prefix, suffix, suffix); - if (align_jumps == 0) + warning (0, "-mregparm is ignored in 64-bit mode"); + if (ix86_regparm > REGPARM_MAX) { - i = atoi (ix86_align_jumps_string); - if (i < 0 || i > MAX_CODE_ALIGN) - error ("%salign-loops=%d%s is not between 0 and %d", - prefix, i, suffix, MAX_CODE_ALIGN); - else - align_jumps = 1 << i; - } - } - - if (ix86_align_funcs_string) - { - warning (0, "%salign-functions%s is obsolete, use -falign-functions%s", - prefix, suffix, suffix); - if (align_functions == 0) - { - i = atoi (ix86_align_funcs_string); - if (i < 0 || i > MAX_CODE_ALIGN) - error ("%salign-loops=%d%s is not between 0 and %d", - prefix, i, suffix, MAX_CODE_ALIGN); - else - align_functions = 1 << i; + error ("-mregparm=%d is not between 0 and %d", + ix86_regparm, REGPARM_MAX); + ix86_regparm = 0; } } + if (TARGET_64BIT) + ix86_regparm = REGPARM_MAX; /* Default align_* from the processor table. */ if (align_loops == 0) @@ -3914,42 +3893,9 @@ ix86_option_override_internal (bool main_args_p) align_functions = processor_target_table[ix86_tune].align_func; } - /* Validate -mbranch-cost= value, or provide default. */ - ix86_branch_cost = ix86_cost->branch_cost; - if (ix86_branch_cost_string) - { - i = atoi (ix86_branch_cost_string); - if (i < 0 || i > 5) - error ("%sbranch-cost=%d%s is not between 0 and 5", prefix, i, suffix); - else - ix86_branch_cost = i; - } - if (ix86_section_threshold_string) - { - i = atoi (ix86_section_threshold_string); - if (i < 0) - error ("%slarge-data-threshold=%d%s is negative", prefix, i, suffix); - else - ix86_section_threshold = i; - } - - if (ix86_tls_dialect_string) - { - if (strcmp (ix86_tls_dialect_string, "gnu") == 0) - ix86_tls_dialect = TLS_DIALECT_GNU; - else if (strcmp (ix86_tls_dialect_string, "gnu2") == 0) - ix86_tls_dialect = TLS_DIALECT_GNU2; - else - error ("bad value (%s) for %stls-dialect=%s %s", - ix86_tls_dialect_string, prefix, suffix, sw); - } - - if (ix87_precision_string) - { - i = atoi (ix87_precision_string); - if (i != 32 && i != 64 && i != 80) - error ("pc%d is not valid precision setting (32, 64 or 80)", i); - } + /* Provide default for -mbranch-cost= value. */ + if (!global_options_set.x_ix86_branch_cost) + ix86_branch_cost = ix86_cost->branch_cost; if (TARGET_64BIT) { @@ -4001,6 +3947,13 @@ ix86_option_override_internal (bool main_args_p) if (!TARGET_80387) target_flags |= MASK_NO_FANCY_MATH_387; + /* On 32bit targets, avoid moving DFmode values in + integer registers when optimizing for size. */ + if (TARGET_64BIT) + target_flags |= TARGET_INTEGER_DFMODE_MOVES; + else if (optimize_size) + target_flags &= ~TARGET_INTEGER_DFMODE_MOVES; + /* Turn on MMX builtins for -msse. */ if (TARGET_SSE) { @@ -4015,23 +3968,24 @@ ix86_option_override_internal (bool main_args_p) /* Validate -mpreferred-stack-boundary= value or default it to PREFERRED_STACK_BOUNDARY_DEFAULT. */ ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT; - if (ix86_preferred_stack_boundary_string) + if (global_options_set.x_ix86_preferred_stack_boundary_arg) { int min = (TARGET_64BIT ? 4 : 2); int max = (TARGET_SEH ? 4 : 12); - i = atoi (ix86_preferred_stack_boundary_string); - if (i < min || i > max) + if (ix86_preferred_stack_boundary_arg < min + || ix86_preferred_stack_boundary_arg > max) { if (min == max) - error ("%spreferred-stack-boundary%s is not supported " - "for this target", prefix, suffix); + error ("-mpreferred-stack-boundary is not supported " + "for this target"); else - error ("%spreferred-stack-boundary=%d%s is not between %d and %d", - prefix, i, suffix, min, max); + error ("-mpreferred-stack-boundary=%d is not between %d and %d", + ix86_preferred_stack_boundary_arg, min, max); } else - ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT; + ix86_preferred_stack_boundary + = (1 << ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT; } /* Set the default value for -mstackrealign. */ @@ -4043,15 +3997,16 @@ ix86_option_override_internal (bool main_args_p) /* Validate -mincoming-stack-boundary= value or default it to MIN_STACK_BOUNDARY/PREFERRED_STACK_BOUNDARY. */ ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary; - if (ix86_incoming_stack_boundary_string) + if (global_options_set.x_ix86_incoming_stack_boundary_arg) { - i = atoi (ix86_incoming_stack_boundary_string); - if (i < (TARGET_64BIT ? 4 : 2) || i > 12) + if (ix86_incoming_stack_boundary_arg < (TARGET_64BIT ? 4 : 2) + || ix86_incoming_stack_boundary_arg > 12) error ("-mincoming-stack-boundary=%d is not between %d and 12", - i, TARGET_64BIT ? 4 : 2); + ix86_incoming_stack_boundary_arg, TARGET_64BIT ? 4 : 2); else { - ix86_user_incoming_stack_boundary = (1 << i) * BITS_PER_UNIT; + ix86_user_incoming_stack_boundary + = (1 << ix86_incoming_stack_boundary_arg) * BITS_PER_UNIT; ix86_incoming_stack_boundary = ix86_user_incoming_stack_boundary; } @@ -4062,61 +4017,44 @@ ix86_option_override_internal (bool main_args_p) && ! TARGET_SSE) error ("%ssseregparm%s used without SSE enabled", prefix, suffix); - ix86_fpmath = TARGET_FPMATH_DEFAULT; - if (ix86_fpmath_string != 0) + if (global_options_set.x_ix86_fpmath) { - if (! strcmp (ix86_fpmath_string, "387")) - ix86_fpmath = FPMATH_387; - else if (! strcmp (ix86_fpmath_string, "sse")) + if (ix86_fpmath & FPMATH_SSE) { if (!TARGET_SSE) { warning (0, "SSE instruction set disabled, using 387 arithmetics"); ix86_fpmath = FPMATH_387; } - else - ix86_fpmath = FPMATH_SSE; - } - else if (! strcmp (ix86_fpmath_string, "387,sse") - || ! strcmp (ix86_fpmath_string, "387+sse") - || ! strcmp (ix86_fpmath_string, "sse,387") - || ! strcmp (ix86_fpmath_string, "sse+387") - || ! strcmp (ix86_fpmath_string, "both")) - { - if (!TARGET_SSE) - { - warning (0, "SSE instruction set disabled, using 387 arithmetics"); - ix86_fpmath = FPMATH_387; - } - else if (!TARGET_80387) + else if ((ix86_fpmath & FPMATH_387) && !TARGET_80387) { warning (0, "387 instruction set disabled, using SSE arithmetics"); ix86_fpmath = FPMATH_SSE; } - else - ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387); } - else - error ("bad value (%s) for %sfpmath=%s %s", - ix86_fpmath_string, prefix, suffix, sw); } + else + ix86_fpmath = TARGET_FPMATH_DEFAULT; /* If the i387 is disabled, then do not return values in it. */ if (!TARGET_80387) target_flags &= ~MASK_FLOAT_RETURNS; /* Use external vectorized library in vectorizing intrinsics. */ - if (ix86_veclibabi_string) - { - if (strcmp (ix86_veclibabi_string, "svml") == 0) + if (global_options_set.x_ix86_veclibabi_type) + switch (ix86_veclibabi_type) + { + case ix86_veclibabi_type_svml: ix86_veclib_handler = ix86_veclibabi_svml; - else if (strcmp (ix86_veclibabi_string, "acml") == 0) + break; + + case ix86_veclibabi_type_acml: ix86_veclib_handler = ix86_veclibabi_acml; - else - error ("unknown vectorization library ABI type (%s) for " - "%sveclibabi=%s %s", ix86_veclibabi_string, - prefix, suffix, sw); - } + break; + + default: + gcc_unreachable (); + } if ((!USE_IX86_FRAME_POINTER || (x86_accumulate_outgoing_args & ix86_tune_mask)) @@ -4153,8 +4091,9 @@ ix86_option_override_internal (bool main_args_p) } /* For sane SSE instruction set generation we need fcomi instruction. - It is safe to enable all CMOVE instructions. */ - if (TARGET_SSE) + It is safe to enable all CMOVE instructions. Also, RDRAND intrinsic + expands to a sequence that includes conditional move. */ + if (TARGET_SSE || TARGET_RDRND) TARGET_CMOVE = 1; /* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix. */ @@ -4400,7 +4339,6 @@ ix86_function_specific_save (struct cl_target_option *ptr) ptr->arch = ix86_arch; ptr->schedule = ix86_schedule; ptr->tune = ix86_tune; - ptr->fpmath = ix86_fpmath; ptr->branch_cost = ix86_branch_cost; ptr->tune_defaulted = ix86_tune_defaulted; ptr->arch_specified = ix86_arch_specified; @@ -4412,7 +4350,6 @@ ix86_function_specific_save (struct cl_target_option *ptr) gcc_assert (ptr->arch == ix86_arch); gcc_assert (ptr->schedule == ix86_schedule); gcc_assert (ptr->tune == ix86_tune); - gcc_assert (ptr->fpmath == ix86_fpmath); gcc_assert (ptr->branch_cost == ix86_branch_cost); } @@ -4429,7 +4366,6 @@ ix86_function_specific_restore (struct cl_target_option *ptr) ix86_arch = (enum processor_type) ptr->arch; ix86_schedule = (enum attr_cpu) ptr->schedule; ix86_tune = (enum processor_type) ptr->tune; - ix86_fpmath = (enum fpmath_unit) ptr->fpmath; ix86_branch_cost = ptr->branch_cost; ix86_tune_defaulted = ptr->tune_defaulted; ix86_arch_specified = ptr->arch_specified; @@ -4463,7 +4399,7 @@ ix86_function_specific_print (FILE *file, int indent, { char *target_string = ix86_target_string (ptr->x_ix86_isa_flags, ptr->x_target_flags, - NULL, NULL, NULL, false); + NULL, NULL, ptr->x_ix86_fpmath, false); fprintf (file, "%*sarch = %d (%s)\n", indent, "", @@ -4479,9 +4415,6 @@ ix86_function_specific_print (FILE *file, int indent, ? cpu_names[ptr->tune] : "<unknown>")); - fprintf (file, "%*sfpmath = %d%s%s\n", indent, "", ptr->fpmath, - (ptr->fpmath & FPMATH_387) ? ", 387" : "", - (ptr->fpmath & FPMATH_SSE) ? ", sse" : ""); fprintf (file, "%*sbranch_cost = %d\n", indent, "", ptr->branch_cost); if (target_string) @@ -4497,13 +4430,15 @@ ix86_function_specific_print (FILE *file, int indent, over the list. */ static bool -ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) +ix86_valid_target_attribute_inner_p (tree args, char *p_strings[], + struct gcc_options *enum_opts_set) { char *next_optstr; bool ret = true; #define IX86_ATTR_ISA(S,O) { S, sizeof (S)-1, ix86_opt_isa, O, 0 } #define IX86_ATTR_STR(S,O) { S, sizeof (S)-1, ix86_opt_str, O, 0 } +#define IX86_ATTR_ENUM(S,O) { S, sizeof (S)-1, ix86_opt_enum, O, 0 } #define IX86_ATTR_YES(S,O,M) { S, sizeof (S)-1, ix86_opt_yes, O, M } #define IX86_ATTR_NO(S,O,M) { S, sizeof (S)-1, ix86_opt_no, O, M } @@ -4513,6 +4448,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) ix86_opt_yes, ix86_opt_no, ix86_opt_str, + ix86_opt_enum, ix86_opt_isa }; @@ -4549,9 +4485,11 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) IX86_ATTR_ISA ("rdrnd", OPT_mrdrnd), IX86_ATTR_ISA ("f16c", OPT_mf16c), + /* enum options */ + IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_), + /* string options */ IX86_ATTR_STR ("arch=", IX86_FUNCTION_SPECIFIC_ARCH), - IX86_ATTR_STR ("fpmath=", IX86_FUNCTION_SPECIFIC_FPMATH), IX86_ATTR_STR ("tune=", IX86_FUNCTION_SPECIFIC_TUNE), /* flag options */ @@ -4592,7 +4530,8 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) for (; args; args = TREE_CHAIN (args)) if (TREE_VALUE (args) - && !ix86_valid_target_attribute_inner_p (TREE_VALUE (args), p_strings)) + && !ix86_valid_target_attribute_inner_p (TREE_VALUE (args), + p_strings, enum_opts_set)) ret = false; return ret; @@ -4648,7 +4587,9 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) type = attrs[i].type; opt_len = attrs[i].len; if (ch == attrs[i].string[0] - && ((type != ix86_opt_str) ? len == opt_len : len > opt_len) + && ((type != ix86_opt_str && type != ix86_opt_enum) + ? len == opt_len + : len > opt_len) && memcmp (p, attrs[i].string, opt_len) == 0) { opt = attrs[i].opt; @@ -4696,6 +4637,23 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) p_strings[opt] = xstrdup (p + opt_len); } + else if (type == ix86_opt_enum) + { + bool arg_ok; + int value; + + arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET); + if (arg_ok) + set_option (&global_options, enum_opts_set, opt, value, + p + opt_len, DK_UNSPECIFIED, input_location, + global_dc); + else + { + error ("attribute(target(\"%s\")) is unknown", orig_p); + ret = false; + } + } + else gcc_unreachable (); } @@ -4710,17 +4668,21 @@ ix86_valid_target_attribute_tree (tree args) { const char *orig_arch_string = ix86_arch_string; const char *orig_tune_string = ix86_tune_string; - const char *orig_fpmath_string = ix86_fpmath_string; + enum fpmath_unit orig_fpmath_set = global_options_set.x_ix86_fpmath; int orig_tune_defaulted = ix86_tune_defaulted; int orig_arch_specified = ix86_arch_specified; - char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL, NULL }; + char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL }; tree t = NULL_TREE; int i; struct cl_target_option *def = TREE_TARGET_OPTION (target_option_default_node); + struct gcc_options enum_opts_set; + + memset (&enum_opts_set, 0, sizeof (enum_opts_set)); /* Process each of the options on the chain. */ - if (! ix86_valid_target_attribute_inner_p (args, option_strings)) + if (! ix86_valid_target_attribute_inner_p (args, option_strings, + &enum_opts_set)) return NULL_TREE; /* If the changed options are different from the default, rerun @@ -4731,7 +4693,7 @@ ix86_valid_target_attribute_tree (tree args) || target_flags != def->x_target_flags || option_strings[IX86_FUNCTION_SPECIFIC_ARCH] || option_strings[IX86_FUNCTION_SPECIFIC_TUNE] - || option_strings[IX86_FUNCTION_SPECIFIC_FPMATH]) + || enum_opts_set.x_ix86_fpmath) { /* If we are using the default tune= or arch=, undo the string assigned, and use the default. */ @@ -4746,10 +4708,13 @@ ix86_valid_target_attribute_tree (tree args) ix86_tune_string = NULL; /* If fpmath= is not set, and we now have sse2 on 32-bit, use it. */ - if (option_strings[IX86_FUNCTION_SPECIFIC_FPMATH]) - ix86_fpmath_string = option_strings[IX86_FUNCTION_SPECIFIC_FPMATH]; + if (enum_opts_set.x_ix86_fpmath) + global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1; else if (!TARGET_64BIT && TARGET_SSE) - ix86_fpmath_string = "sse,387"; + { + ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387); + global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1; + } /* Do any overrides, such as arch=xxx, or tune=xxx support. */ ix86_option_override_internal (false); @@ -4763,7 +4728,7 @@ ix86_valid_target_attribute_tree (tree args) ix86_arch_string = orig_arch_string; ix86_tune_string = orig_tune_string; - ix86_fpmath_string = orig_fpmath_string; + global_options_set.x_ix86_fpmath = orig_fpmath_set; /* Free up memory allocated to hold the strings */ for (i = 0; i < IX86_FUNCTION_SPECIFIC_MAX; i++) @@ -4861,7 +4826,7 @@ ix86_can_inline_p (tree caller, tree callee) else if (caller_opts->tune != callee_opts->tune) ret = false; - else if (caller_opts->fpmath != callee_opts->fpmath) + else if (caller_opts->x_ix86_fpmath != callee_opts->x_ix86_fpmath) ret = false; else if (caller_opts->branch_cost != callee_opts->branch_cost) @@ -8643,17 +8608,17 @@ standard_sse_constant_opcode (rtx insn, rtx x) switch (get_attr_mode (insn)) { case MODE_V4SF: - return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0"; + return "%vxorps\t%0, %d0"; case MODE_V2DF: if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0"; + return "%vxorps\t%0, %d0"; else - return TARGET_AVX ? "vxorpd\t%0, %0, %0" : "xorpd\t%0, %0"; + return "%vxorpd\t%0, %d0"; case MODE_TI: if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0"; + return "%vxorps\t%0, %d0"; else - return TARGET_AVX ? "vpxor\t%0, %0, %0" : "pxor\t%0, %0"; + return "%vpxor\t%0, %d0"; case MODE_V8SF: return "vxorps\t%x0, %x0, %x0"; case MODE_V4DF: @@ -8670,7 +8635,7 @@ standard_sse_constant_opcode (rtx insn, rtx x) break; } case 2: - return TARGET_AVX ? "vpcmpeqd\t%0, %0, %0" : "pcmpeqd\t%0, %0"; + return "%vpcmpeqd\t%0, %d0"; default: break; } @@ -8804,6 +8769,10 @@ ix86_code_end (void) rtx xops[2]; int regno; +#ifdef TARGET_SOLARIS + solaris_code_end (); +#endif + for (regno = AX_REG; regno <= SP_REG; regno++) { char name[32]; @@ -9064,9 +9033,10 @@ ix86_select_alt_pic_regnum (void) return INVALID_REGNUM; } -/* Return 1 if we need to save REGNO. */ -static int -ix86_save_reg (unsigned int regno, int maybe_eh_return) +/* Return TRUE if we need to save REGNO. */ + +static bool +ix86_save_reg (unsigned int regno, bool maybe_eh_return) { if (pic_offset_table_rtx && regno == REAL_PIC_OFFSET_TABLE_REGNUM @@ -9074,11 +9044,7 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return) || crtl->profile || crtl->calls_eh_return || crtl->uses_const_pool)) - { - if (ix86_select_alt_pic_regnum () != INVALID_REGNUM) - return 0; - return 1; - } + return ix86_select_alt_pic_regnum () == INVALID_REGNUM; if (crtl->calls_eh_return && maybe_eh_return) { @@ -9089,12 +9055,12 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return) if (test == INVALID_REGNUM) break; if (test == regno) - return 1; + return true; } } if (crtl->drap_reg && regno == REGNO (crtl->drap_reg)) - return 1; + return true; return (df_regs_ever_live_p (regno) && !call_used_regs[regno] @@ -10898,7 +10864,7 @@ ix86_emit_leave (void) First register is restored from CFA - CFA_OFFSET. */ static void ix86_emit_restore_regs_using_mov (HOST_WIDE_INT cfa_offset, - int maybe_eh_return) + bool maybe_eh_return) { struct machine_function *m = cfun->machine; unsigned int regno; @@ -10937,7 +10903,7 @@ ix86_emit_restore_regs_using_mov (HOST_WIDE_INT cfa_offset, First register is restored from CFA - CFA_OFFSET. */ static void ix86_emit_restore_sse_regs_using_mov (HOST_WIDE_INT cfa_offset, - int maybe_eh_return) + bool maybe_eh_return) { unsigned int regno; @@ -11556,7 +11522,7 @@ ix86_expand_split_stack_prologue (void) } call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, fn), GEN_INT (UNITS_PER_WORD), constm1_rtx, - NULL_RTX, 0); + NULL_RTX, false); add_function_usage_to (call_insn, call_fusage); /* In order to make call/return prediction work right, we now need @@ -12657,7 +12623,7 @@ legitimize_pic_address (rtx orig, rtx reg) /* Load the thread pointer. If TO_REG is true, force it into a register. */ static rtx -get_thread_pointer (int to_reg) +get_thread_pointer (bool to_reg) { rtx tp, reg, insn; @@ -12672,76 +12638,154 @@ get_thread_pointer (int to_reg) return reg; } +/* Construct the SYMBOL_REF for the tls_get_addr function. */ + +static GTY(()) rtx ix86_tls_symbol; + +static rtx +ix86_tls_get_addr (void) +{ + if (!ix86_tls_symbol) + { + const char *sym + = ((TARGET_ANY_GNU_TLS && !TARGET_64BIT) + ? "___tls_get_addr" : "__tls_get_addr"); + + ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, sym); + } + + return ix86_tls_symbol; +} + +/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */ + +static GTY(()) rtx ix86_tls_module_base_symbol; + +rtx +ix86_tls_module_base (void) +{ + if (!ix86_tls_module_base_symbol) + { + ix86_tls_module_base_symbol + = gen_rtx_SYMBOL_REF (Pmode, "_TLS_MODULE_BASE_"); + + SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol) + |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT; + } + + return ix86_tls_module_base_symbol; +} + /* A subroutine of ix86_legitimize_address and ix86_expand_move. FOR_MOV is false if we expect this to be used for a memory address and true if we expect to load the address into a register. */ static rtx -legitimize_tls_address (rtx x, enum tls_model model, int for_mov) +legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) { - rtx dest, base, off, pic, tp; + rtx dest, base, off; + rtx pic = NULL_RTX, tp = NULL_RTX; int type; switch (model) { case TLS_MODEL_GLOBAL_DYNAMIC: dest = gen_reg_rtx (Pmode); - tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0; - if (TARGET_64BIT && ! TARGET_GNU2_TLS) + if (!TARGET_64BIT) { - rtx rax = gen_rtx_REG (Pmode, AX_REG), insns; - - start_sequence (); - emit_call_insn (gen_tls_global_dynamic_64 (rax, x)); - insns = get_insns (); - end_sequence (); - - RTL_CONST_CALL_P (insns) = 1; - emit_libcall_block (insns, dest, rax, x); + if (flag_pic) + pic = pic_offset_table_rtx; + else + { + pic = gen_reg_rtx (Pmode); + emit_insn (gen_set_got (pic)); + } } - else if (TARGET_64BIT && TARGET_GNU2_TLS) - emit_insn (gen_tls_global_dynamic_64 (dest, x)); - else - emit_insn (gen_tls_global_dynamic_32 (dest, x)); if (TARGET_GNU2_TLS) { + if (TARGET_64BIT) + emit_insn (gen_tls_dynamic_gnu2_64 (dest, x)); + else + emit_insn (gen_tls_dynamic_gnu2_32 (dest, x, pic)); + + tp = get_thread_pointer (true); dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest)); set_unique_reg_note (get_last_insn (), REG_EQUIV, x); } + else + { + rtx caddr = ix86_tls_get_addr (); + + if (TARGET_64BIT) + { + rtx rax = gen_rtx_REG (Pmode, AX_REG), insns; + + start_sequence (); + emit_call_insn (gen_tls_global_dynamic_64 (rax, x, caddr)); + insns = get_insns (); + end_sequence (); + + RTL_CONST_CALL_P (insns) = 1; + emit_libcall_block (insns, dest, rax, x); + } + else + emit_insn (gen_tls_global_dynamic_32 (dest, x, pic, caddr)); + } break; case TLS_MODEL_LOCAL_DYNAMIC: base = gen_reg_rtx (Pmode); - tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0; - if (TARGET_64BIT && ! TARGET_GNU2_TLS) + if (!TARGET_64BIT) { - rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, note; - - start_sequence (); - emit_call_insn (gen_tls_local_dynamic_base_64 (rax)); - insns = get_insns (); - end_sequence (); - - note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL); - note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note); - RTL_CONST_CALL_P (insns) = 1; - emit_libcall_block (insns, base, rax, note); + if (flag_pic) + pic = pic_offset_table_rtx; + else + { + pic = gen_reg_rtx (Pmode); + emit_insn (gen_set_got (pic)); + } } - else if (TARGET_64BIT && TARGET_GNU2_TLS) - emit_insn (gen_tls_local_dynamic_base_64 (base)); - else - emit_insn (gen_tls_local_dynamic_base_32 (base)); if (TARGET_GNU2_TLS) { - rtx x = ix86_tls_module_base (); + rtx tmp = ix86_tls_module_base (); + + if (TARGET_64BIT) + emit_insn (gen_tls_dynamic_gnu2_64 (base, tmp)); + else + emit_insn (gen_tls_dynamic_gnu2_32 (base, tmp, pic)); + tp = get_thread_pointer (true); set_unique_reg_note (get_last_insn (), REG_EQUIV, - gen_rtx_MINUS (Pmode, x, tp)); + gen_rtx_MINUS (Pmode, tmp, tp)); + } + else + { + rtx caddr = ix86_tls_get_addr (); + + if (TARGET_64BIT) + { + rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, eqv; + + start_sequence (); + emit_call_insn (gen_tls_local_dynamic_base_64 (rax, caddr)); + insns = get_insns (); + end_sequence (); + + /* Attach a unique REG_EQUIV, to allow the RTL optimizers to + share the LD_BASE result with other LD model accesses. */ + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), + UNSPEC_TLS_LD_BASE); + + RTL_CONST_CALL_P (insns) = 1; + emit_libcall_block (insns, base, rax, eqv); + } + else + emit_insn (gen_tls_local_dynamic_base_32 (base, pic, caddr)); } off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF); @@ -12755,7 +12799,6 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov) set_unique_reg_note (get_last_insn (), REG_EQUIV, x); } - break; case TLS_MODEL_INITIAL_EXEC: @@ -15158,7 +15201,7 @@ emit_i387_cw_initialization (int mode) operand may be [SDX]Fmode. */ const char * -output_fix_trunc (rtx insn, rtx *operands, int fisttp) +output_fix_trunc (rtx insn, rtx *operands, bool fisttp) { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; int dimode_p = GET_MODE (operands[0]) == DImode; @@ -15223,7 +15266,7 @@ output_387_ffreep (rtx *operands ATTRIBUTE_UNUSED, int opno) should be used. UNORDERED_P is true when fucom should be used. */ const char * -output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p) +output_fp_compare (rtx insn, rtx *operands, bool eflags_p, bool unordered_p) { int stack_top_dies; rtx cmp_op0, cmp_op1; @@ -20797,8 +20840,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, algs = &cost->memset[TARGET_64BIT != 0]; else algs = &cost->memcpy[TARGET_64BIT != 0]; - if (stringop_alg != no_stringop && ALG_USABLE_P (stringop_alg)) - return stringop_alg; + if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg)) + return ix86_stringop_alg; /* rep; movq or rep; movl is the smallest variant. */ else if (!optimize_for_speed) { @@ -21923,7 +21966,7 @@ construct_plt_address (rtx symbol) rtx ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx callarg2, - rtx pop, int sibcall) + rtx pop, bool sibcall) { rtx use = NULL, call; @@ -22055,23 +22098,25 @@ ix86_split_call_vzeroupper (rtx insn, rtx vzeroupper) /* Output the assembly for a call instruction. */ const char * -ix86_output_call_insn (rtx insn, rtx call_op, int addr_op) +ix86_output_call_insn (rtx insn, rtx call_op) { bool direct_p = constant_call_address_operand (call_op, Pmode); bool seh_nop_p = false; - - gcc_assert (addr_op == 0 || addr_op == 1); + const char *xasm; if (SIBLING_CALL_P (insn)) { if (direct_p) - return addr_op ? "jmp\t%P1" : "jmp\t%P0"; + xasm = "jmp\t%P0"; /* SEH epilogue detection requires the indirect branch case to include REX.W. */ else if (TARGET_SEH) - return addr_op ? "rex.W jmp %A1" : "rex.W jmp %A0"; + xasm = "rex.W jmp %A0"; else - return addr_op ? "jmp\t%A1" : "jmp\t%A0"; + xasm = "jmp\t%A0"; + + output_asm_insn (xasm, &call_op); + return ""; } /* SEH unwinding can require an extra nop to be emitted in several @@ -22105,19 +22150,16 @@ ix86_output_call_insn (rtx insn, rtx call_op, int addr_op) } if (direct_p) - { - if (seh_nop_p) - return addr_op ? "call\t%P1\n\tnop" : "call\t%P0\n\tnop"; - else - return addr_op ? "call\t%P1" : "call\t%P0"; - } + xasm = "call\t%P0"; else - { - if (seh_nop_p) - return addr_op ? "call\t%A1\n\tnop" : "call\t%A0\n\tnop"; - else - return addr_op ? "call\t%A1" : "call\t%A0"; - } + xasm = "call\t%A0"; + + output_asm_insn (xasm, &call_op); + + if (seh_nop_p) + return "nop"; + + return ""; } /* Clear stack slot assignments remembered from previous functions. @@ -22166,43 +22208,6 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n) ix86_stack_locals = s; return s->rtl; } - -/* Construct the SYMBOL_REF for the tls_get_addr function. */ - -static GTY(()) rtx ix86_tls_symbol; -rtx -ix86_tls_get_addr (void) -{ - - if (!ix86_tls_symbol) - { - ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, - (TARGET_ANY_GNU_TLS - && !TARGET_64BIT) - ? "___tls_get_addr" - : "__tls_get_addr"); - } - - return ix86_tls_symbol; -} - -/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */ - -static GTY(()) rtx ix86_tls_module_base_symbol; -rtx -ix86_tls_module_base (void) -{ - - if (!ix86_tls_module_base_symbol) - { - ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode, - "_TLS_MODULE_BASE_"); - SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol) - |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT; - } - - return ix86_tls_module_base_symbol; -} /* Calculate the length of the memory address in the instruction encoding. Does not include the one-byte modrm, opcode, or prefix. */ @@ -22326,7 +22331,7 @@ memory_address_length (rtx addr) /* Compute default value for "length_immediate" attribute. When SHORTFORM is set, expect that insn have 8bit immediate alternative. */ int -ix86_attr_length_immediate_default (rtx insn, int shortform) +ix86_attr_length_immediate_default (rtx insn, bool shortform) { int len = 0; int i; @@ -22436,8 +22441,7 @@ ix86_attr_length_address_default (rtx insn) 2 or 3 byte VEX prefix and 1 opcode byte. */ int -ix86_attr_length_vex_default (rtx insn, int has_0f_opcode, - int has_vex_w) +ix86_attr_length_vex_default (rtx insn, bool has_0f_opcode, bool has_vex_w) { int i; @@ -22504,10 +22508,10 @@ ix86_issue_rate (void) } } -/* A subroutine of ix86_adjust_cost -- return true iff INSN reads flags set +/* A subroutine of ix86_adjust_cost -- return TRUE iff INSN reads flags set by DEP_INSN and nothing set by DEP_INSN. */ -static int +static bool ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type) { rtx set, set2; @@ -22517,7 +22521,7 @@ ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type) && insn_type != TYPE_ICMOV && insn_type != TYPE_FCMOV && insn_type != TYPE_IBR) - return 0; + return false; if ((set = single_set (dep_insn)) != 0) { @@ -22533,20 +22537,20 @@ ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type) set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0)); } else - return 0; + return false; if (!REG_P (set) || REGNO (set) != FLAGS_REG) - return 0; + return false; /* This test is true if the dependent insn reads the flags but not any other potentially set register. */ if (!reg_overlap_mentioned_p (set, PATTERN (insn))) - return 0; + return false; if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn))) - return 0; + return false; - return 1; + return true; } /* Return true iff USE_INSN has a memory address with operands set by @@ -27398,7 +27402,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, && !(ix86_builtins_isa[fcode].isa & ix86_isa_flags)) { char *opts = ix86_target_string (ix86_builtins_isa[fcode].isa, 0, NULL, - NULL, NULL, false); + NULL, (enum fpmath_unit) 0, false); if (!opts) error ("%qE needs unknown isa option", fndecl); @@ -27610,6 +27614,12 @@ rdrand_step: op0 = gen_reg_rtx (mode0); emit_insn (GEN_FCN (icode) (op0)); + arg0 = CALL_EXPR_ARG (exp, 0); + op1 = expand_normal (arg0); + if (!address_operand (op1, VOIDmode)) + op1 = copy_addr_to_reg (op1); + emit_move_insn (gen_rtx_MEM (mode0, op1), op0); + op1 = gen_reg_rtx (SImode); emit_move_insn (op1, CONST1_RTX (SImode)); @@ -27624,17 +27634,13 @@ rdrand_step: else op2 = gen_rtx_SUBREG (SImode, op0, 0); + if (target == 0) + target = gen_reg_rtx (SImode); + pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx); - emit_insn (gen_rtx_SET (VOIDmode, op1, + emit_insn (gen_rtx_SET (VOIDmode, target, gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1))); - emit_move_insn (target, op1); - - arg0 = CALL_EXPR_ARG (exp, 0); - op1 = expand_normal (arg0); - if (!address_operand (op1, VOIDmode)) - op1 = copy_addr_to_reg (op1); - emit_move_insn (gen_rtx_MEM (mode0, op1), op0); return target; default: @@ -28508,7 +28514,7 @@ ix86_preferred_reload_class (rtx x, reg_class_t regclass) zero above. We only want to wind up preferring 80387 registers if we plan on doing computation with them. */ if (TARGET_80387 - && standard_80387_constant_p (x)) + && standard_80387_constant_p (x) > 0) { /* Limit class to non-sse. */ if (regclass == FLOAT_SSE_REGS) @@ -28959,7 +28965,8 @@ ix86_register_move_cost (enum machine_mode mode, reg_class_t class1_i, return 2; } -/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */ +/* Return TRUE if hard register REGNO can hold a value of machine-mode + MODE. */ bool ix86_hard_regno_mode_ok (int regno, enum machine_mode mode) @@ -28970,7 +28977,7 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode) if (GET_MODE_CLASS (mode) == MODE_CC || GET_MODE_CLASS (mode) == MODE_RANDOM || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) - return 0; + return false; if (FP_REGNO_P (regno)) return VALID_FP_MODE_P (mode); if (SSE_REGNO_P (regno)) @@ -29000,26 +29007,26 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode) /* Take care for QImode values - they can be in non-QI regs, but then they do cause partial register stalls. */ if (regno <= BX_REG || TARGET_64BIT) - return 1; + return true; if (!TARGET_PARTIAL_REG_STALL) - return 1; - return reload_in_progress || reload_completed; + return true; + return !can_create_pseudo_p (); } /* We handle both integer and floats in the general purpose registers. */ else if (VALID_INT_MODE_P (mode)) - return 1; + return true; else if (VALID_FP_MODE_P (mode)) - return 1; + return true; else if (VALID_DFP_MODE_P (mode)) - return 1; + return true; /* Lots of MMX code casts 8 byte vector modes to DImode. If we then go on to use that value in smaller contexts, this can easily force a pseudo to be allocated to GENERAL_REGS. Since this is no worse than supporting DImode, allow it. */ else if (VALID_MMX_REG_MODE_3DNOW (mode) || VALID_MMX_REG_MODE (mode)) - return 1; + return true; - return 0; + return false; } /* A subroutine of ix86_modes_tieable_p. Return true if MODE is a @@ -32148,9 +32155,10 @@ void ix86_emit_swsqrtsf (rtx res, rtx a, enum machine_mode mode, gen_rtx_MULT (mode, e2, e3))); } +#ifdef TARGET_SOLARIS /* Solaris implementation of TARGET_ASM_NAMED_SECTION. */ -static void ATTRIBUTE_UNUSED +static void i386_solaris_elf_named_section (const char *name, unsigned int flags, tree decl) { @@ -32164,8 +32172,18 @@ i386_solaris_elf_named_section (const char *name, unsigned int flags, flags & SECTION_WRITE ? "aw" : "a"); return; } + +#ifndef USE_GAS + if (HAVE_COMDAT_GROUP && flags & SECTION_LINKONCE) + { + solaris_elf_asm_comdat_section (name, flags, decl); + return; + } +#endif + default_elf_asm_named_section (name, flags, decl); } +#endif /* TARGET_SOLARIS */ /* Return the mangling of TYPE if it is an extended fundamental type. */ diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 4137ecc6728..8badcbbce61 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -79,18 +79,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "config/vxworks-dummy.h" -/* Algorithm to expand string function with. */ -enum stringop_alg -{ - no_stringop, - libcall, - rep_prefix_1_byte, - rep_prefix_4_byte, - rep_prefix_8_byte, - loop_1_byte, - loop, - unrolled_loop -}; +#include "config/i386/i386-opts.h" #define MAX_STRINGOP_ALGS 4 @@ -506,16 +495,6 @@ extern tree x86_mfence; /* This is re-defined by cygming.h. */ #define TARGET_SEH 0 -/* Available call abi. */ -enum calling_abi -{ - SYSV_ABI = 0, - MS_ABI = 1 -}; - -/* The abi used by target. */ -extern enum calling_abi ix86_abi; - /* The default abi used by target. */ #define DEFAULT_ABI SYSV_ABI @@ -2050,50 +2029,13 @@ enum processor_type extern enum processor_type ix86_tune; extern enum processor_type ix86_arch; -enum fpmath_unit -{ - FPMATH_387 = 1, - FPMATH_SSE = 2 -}; - -extern enum fpmath_unit ix86_fpmath; - -enum tls_dialect -{ - TLS_DIALECT_GNU, - TLS_DIALECT_GNU2, - TLS_DIALECT_SUN -}; - -extern enum tls_dialect ix86_tls_dialect; - -enum cmodel { - CM_32, /* The traditional 32-bit ABI. */ - CM_SMALL, /* Assumes all code and data fits in the low 31 bits. */ - CM_KERNEL, /* Assumes all code and data fits in the high 31 bits. */ - CM_MEDIUM, /* Assumes code fits in the low 31 bits; data unlimited. */ - CM_LARGE, /* No assumptions. */ - CM_SMALL_PIC, /* Assumes code+data+got/plt fits in a 31 bit region. */ - CM_MEDIUM_PIC,/* Assumes code+got/plt fits in a 31 bit region. */ - CM_LARGE_PIC /* No assumptions. */ -}; - -extern enum cmodel ix86_cmodel; - /* Size of the RED_ZONE area. */ #define RED_ZONE_SIZE 128 /* Reserved area of the red zone for temporaries. */ #define RED_ZONE_RESERVE 8 -enum asm_dialect { - ASM_ATT, - ASM_INTEL -}; - -extern enum asm_dialect ix86_asm_dialect; extern unsigned int ix86_preferred_stack_boundary; extern unsigned int ix86_incoming_stack_boundary; -extern int ix86_branch_cost, ix86_section_threshold; /* Smallest class containing REGNO. */ extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER]; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b1fc57314a2..49f1ee747fc 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -414,9 +414,9 @@ (const_int 0) (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1, imul,icmp,push,pop") - (symbol_ref "ix86_attr_length_immediate_default(insn,1)") + (symbol_ref "ix86_attr_length_immediate_default (insn, true)") (eq_attr "type" "imov,test") - (symbol_ref "ix86_attr_length_immediate_default(insn,0)") + (symbol_ref "ix86_attr_length_immediate_default (insn, false)") (eq_attr "type" "call") (if_then_else (match_operand 0 "constant_call_address_operand" "") (const_int 4) @@ -524,11 +524,11 @@ (if_then_else (and (eq_attr "prefix_0f" "1") (eq_attr "prefix_extra" "0")) (if_then_else (eq_attr "prefix_vex_w" "1") - (symbol_ref "ix86_attr_length_vex_default (insn, 1, 1)") - (symbol_ref "ix86_attr_length_vex_default (insn, 1, 0)")) + (symbol_ref "ix86_attr_length_vex_default (insn, true, true)") + (symbol_ref "ix86_attr_length_vex_default (insn, true, false)")) (if_then_else (eq_attr "prefix_vex_w" "1") - (symbol_ref "ix86_attr_length_vex_default (insn, 0, 1)") - (symbol_ref "ix86_attr_length_vex_default (insn, 0, 0)")))) + (symbol_ref "ix86_attr_length_vex_default (insn, false, true)") + (symbol_ref "ix86_attr_length_vex_default (insn, false, false)")))) ;; Set when modrm byte is used. (define_attr "modrm" "" @@ -1262,7 +1262,7 @@ UNSPEC_FNSTSW))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set (attr "mode") @@ -1309,7 +1309,7 @@ (match_operand:XF 2 "register_operand" "f"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set_attr "mode" "XF")]) @@ -1343,7 +1343,7 @@ (match_operand:MODEF 2 "nonimmediate_operand" "fm"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set_attr "mode" "<MODE>")]) @@ -1378,7 +1378,7 @@ UNSPEC_FNSTSW))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" - "* return output_fp_compare (insn, operands, 0, 1);" + "* return output_fp_compare (insn, operands, false, true);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set (attr "mode") @@ -1428,7 +1428,7 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && (TARGET_USE_<MODE>MODE_FIOP || optimize_function_for_size_p (cfun)) && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set_attr "fp_int_src" "true") @@ -1504,7 +1504,7 @@ "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 0);" + "* return output_fp_compare (insn, operands, true, false);" [(set_attr "type" "fcmp,ssecomi") (set_attr "prefix" "orig,maybe_vex") (set (attr "mode") @@ -1533,7 +1533,7 @@ "TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 0);" + "* return output_fp_compare (insn, operands, true, false);" [(set_attr "type" "ssecomi") (set_attr "prefix" "maybe_vex") (set (attr "mode") @@ -1557,7 +1557,7 @@ && TARGET_CMOVE && !(SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && TARGET_SSE_MATH) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 0);" + "* return output_fp_compare (insn, operands, true, false);" [(set_attr "type" "fcmp") (set (attr "mode") (cond [(match_operand:SF 1 "" "") @@ -1577,7 +1577,7 @@ "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, true, true);" [(set_attr "type" "fcmp,ssecomi") (set_attr "prefix" "orig,maybe_vex") (set (attr "mode") @@ -1606,7 +1606,7 @@ "TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, true, true);" [(set_attr "type" "ssecomi") (set_attr "prefix" "maybe_vex") (set (attr "mode") @@ -1630,7 +1630,7 @@ && TARGET_CMOVE && !(SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && TARGET_SSE_MATH) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, true, true);" [(set_attr "type" "fcmp") (set (attr "mode") (cond [(match_operand:SF 1 "" "") @@ -2702,10 +2702,14 @@ [(const_int 0)] "ix86_split_long_move (operands); DONE;") +;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. +;; Size of pushdf using integer instructions is 2+2*memory operand size +;; On the average, pushdf using integers can be still shorter. + (define_insn "*pushdf" [(set (match_operand:DF 0 "push_operand" "=<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y2"))] - "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES" + (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFo,Y2"))] + "" { /* This insn should be already split before reg-stack. */ gcc_unreachable (); @@ -2714,23 +2718,6 @@ (set_attr "unit" "i387,*,*") (set_attr "mode" "DF,SI,DF")]) -;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. -;; Size of pushdf using integer instructions is 2+2*memory operand size -;; On the average, pushdf using integers can be still shorter. Allow this -;; pattern for optimize_size too. - -(define_insn "*pushdf_nointeger" - [(set (match_operand:DF 0 "push_operand" "=<,<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y2"))] - "!(TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES)" -{ - /* This insn should be already split before reg-stack. */ - gcc_unreachable (); -} - [(set_attr "type" "multi") - (set_attr "unit" "i387,*,*,*") - (set_attr "mode" "DF,SI,SI,DF")]) - ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:DF 0 "push_operand" "") @@ -2822,14 +2809,14 @@ return "%vmovaps\t{%1, %0|%0, %1}"; else return "%vmovdqa\t{%1, %0|%0, %1}"; + case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; + return standard_sse_constant_opcode (insn, operands[1]); + case 3: case 4: return "#"; + default: gcc_unreachable (); } @@ -2862,42 +2849,14 @@ "ix86_split_long_move (operands); DONE;") (define_insn "*movxf_internal" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o") - (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))] - "optimize_function_for_speed_p (cfun) - && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed - || GET_CODE (operands[1]) != CONST_DOUBLE - || memory_operand (operands[0], XFmode))" -{ - switch (which_alternative) - { - case 0: - case 1: - return output_387_reg_move (insn, operands); - - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: case 4: - return "#"; - - default: - gcc_unreachable (); - } -} - [(set_attr "type" "fmov,fmov,fmov,multi,multi") - (set_attr "mode" "XF,XF,XF,SI,SI")]) - -;; Do not use integer registers when optimizing for size -(define_insn "*movxf_internal_nointeger" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o") - (match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))] - "optimize_function_for_size_p (cfun) - && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed - || standard_80387_constant_p (operands[1]) + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,Yx*r ,o") + (match_operand:XF 1 "general_operand" "fm,f,G,Yx*roF,FYx*r"))] + "!(MEM_P (operands[0]) && MEM_P (operands[1])) + && (!can_create_pseudo_p () + || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE + || (optimize_function_for_size_p (cfun) + && standard_80387_constant_p (operands[1]) > 0) || memory_operand (operands[0], XFmode))" { switch (which_alternative) @@ -2938,12 +2897,14 @@ (match_operand:DF 1 "general_operand" "fm,f,G,rm,r,F ,F ,C ,Y2*x,m ,Y2*x,r ,Yi"))] "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed + && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!(TARGET_SSE2 && TARGET_SSE_MATH) - && optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1])) || GET_CODE (operands[1]) != CONST_DOUBLE + || (optimize_function_for_size_p (cfun) + && ((!(TARGET_SSE2 && TARGET_SSE_MATH) + && standard_80387_constant_p (operands[1]) > 0) + || (TARGET_SSE2 && TARGET_SSE_MATH + && standard_sse_constant_p (operands[1])))) || memory_operand (operands[0], DFmode))" { switch (which_alternative) @@ -2966,23 +2927,8 @@ return "#"; case 7: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "%vxorps\t%0, %d0"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vxorpd\t%0, %d0"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; - default: - gcc_unreachable (); - } + return standard_sse_constant_opcode (insn, operands[1]); + case 8: case 9: case 10: @@ -3094,21 +3040,25 @@ ] (const_string "DF")))]) +;; Possible store forwarding (partial memory) stall in alternative 4. (define_insn "*movdf_internal" [(set (match_operand:DF 0 "nonimmediate_operand" - "=f,m,f,r ,o ,Y2*x,Y2*x,Y2*x,m ") + "=f,m,f,Yd*r ,o ,Y2*x,Y2*x,Y2*x,m ") (match_operand:DF 1 "general_operand" - "fm,f,G,roF,Fr,C ,Y2*x,m ,Y2*x"))] + "fm,f,G,Yd*roF,FYd*r,C ,Y2*x,m ,Y2*x"))] "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && optimize_function_for_speed_p (cfun) - && TARGET_INTEGER_DFMODE_MOVES - && (reload_in_progress || reload_completed + && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!(TARGET_SSE2 && TARGET_SSE_MATH) - && optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1])) || GET_CODE (operands[1]) != CONST_DOUBLE - || memory_operand (operands[0], DFmode))" + || (!TARGET_INTEGER_DFMODE_MOVES + && ((!(TARGET_SSE2 && TARGET_SSE_MATH) + && standard_80387_constant_p (operands[1]) > 0) + || (TARGET_SSE2 && TARGET_SSE_MATH + && standard_sse_constant_p (operands[1]))) + && !memory_operand (operands[0], DFmode)) + || ((TARGET_INTEGER_DFMODE_MOVES + || !TARGET_MEMORY_MISMATCH_STALL) + && memory_operand (operands[0], DFmode)))" { switch (which_alternative) { @@ -3124,180 +3074,8 @@ return "#"; case 5: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "%vxorps\t%0, %d0"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vxorpd\t%0, %d0"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; - default: - gcc_unreachable (); - } - case 6: - case 7: - case 8: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "%vmovaps\t{%1, %0|%0, %1}"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vmovaps\t{%1, %0|%0, %1}"; - else - return "%vmovapd\t{%1, %0|%0, %1}"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vmovaps\t{%1, %0|%0, %1}"; - else - return "%vmovdqa\t{%1, %0|%0, %1}"; - case MODE_DI: - return "%vmovq\t{%1, %0|%0, %1}"; - case MODE_DF: - if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1])) - return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; - else - return "%vmovsd\t{%1, %0|%0, %1}"; - case MODE_V1DF: - if (TARGET_AVX && REG_P (operands[0])) - return "vmovlpd\t{%1, %0, %0|%0, %0, %1}"; - else - return "%vmovlpd\t{%1, %0|%0, %1}"; - case MODE_V2SF: - if (TARGET_AVX && REG_P (operands[0])) - return "vmovlps\t{%1, %0, %0|%0, %0, %1}"; - else - return "%vmovlps\t{%1, %0|%0, %1}"; - default: - gcc_unreachable (); - } + return standard_sse_constant_opcode (insn, operands[1]); - default: - gcc_unreachable (); - } -} - [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov") - (set (attr "prefix") - (if_then_else (eq_attr "alternative" "0,1,2,3,4") - (const_string "orig") - (const_string "maybe_vex"))) - (set (attr "prefix_data16") - (if_then_else (eq_attr "mode" "V1DF") - (const_string "1") - (const_string "*"))) - (set (attr "mode") - (cond [(eq_attr "alternative" "0,1,2") - (const_string "DF") - (eq_attr "alternative" "3,4") - (const_string "SI") - - /* For SSE1, we have many fewer alternatives. */ - (eq (symbol_ref "TARGET_SSE2") (const_int 0)) - (cond [(eq_attr "alternative" "5,6") - (const_string "V4SF") - ] - (const_string "V2SF")) - - /* xorps is one byte shorter. */ - (eq_attr "alternative" "5") - (cond [(ne (symbol_ref "optimize_function_for_size_p (cfun)") - (const_int 0)) - (const_string "V4SF") - (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") - (const_int 0)) - (const_string "TI") - ] - (const_string "V2DF")) - - /* For architectures resolving dependencies on - whole SSE registers use APD move to break dependency - chains, otherwise use short move to avoid extra work. - - movaps encodes one byte shorter. */ - (eq_attr "alternative" "6") - (cond - [(ne (symbol_ref "optimize_function_for_size_p (cfun)") - (const_int 0)) - (const_string "V4SF") - (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (const_int 0)) - (const_string "V2DF") - ] - (const_string "DF")) - /* For architectures resolving dependencies on register - parts we may avoid extra work to zero out upper part - of register. */ - (eq_attr "alternative" "7") - (if_then_else - (ne (symbol_ref "TARGET_SSE_SPLIT_REGS") - (const_int 0)) - (const_string "V1DF") - (const_string "DF")) - ] - (const_string "DF")))]) - -;; Moving is usually shorter when only FP registers are used. This separate -;; movdf pattern avoids the use of integer registers for FP operations -;; when optimizing for size. - -(define_insn "*movdf_internal_nointeger" - [(set (match_operand:DF 0 "nonimmediate_operand" - "=f,m,f,*r ,o ,Y2*x,Y2*x,Y2*x ,m ") - (match_operand:DF 1 "general_operand" - "fm,f,G,*roF,F*r,C ,Y2*x,mY2*x,Y2*x"))] - "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (optimize_function_for_size_p (cfun) - || !TARGET_INTEGER_DFMODE_MOVES) - && (reload_in_progress || reload_completed - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!(TARGET_SSE2 && TARGET_SSE_MATH) - && optimize_function_for_size_p (cfun) - && !memory_operand (operands[0], DFmode) - && standard_80387_constant_p (operands[1])) - || GET_CODE (operands[1]) != CONST_DOUBLE - || ((optimize_function_for_size_p (cfun) - || !TARGET_MEMORY_MISMATCH_STALL - || reload_in_progress || reload_completed) - && memory_operand (operands[0], DFmode)))" -{ - switch (which_alternative) - { - case 0: - case 1: - return output_387_reg_move (insn, operands); - - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: - return "#"; - - case 5: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "%vxorps\t%0, %d0"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vxorpd\t%0, %d0"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; - default: - gcc_unreachable (); - } case 6: case 7: case 8: @@ -3420,11 +3198,14 @@ (match_operand:SF 1 "general_operand" "fm,f,G,rmF,Fr,C,x,xm,x,m ,*y,*y ,r ,Yi,r ,*Ym"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed + && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!TARGET_SSE_MATH && optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1])) || GET_CODE (operands[1]) != CONST_DOUBLE + || (optimize_function_for_size_p (cfun) + && ((!TARGET_SSE_MATH + && standard_80387_constant_p (operands[1]) > 0) + || (TARGET_SSE_MATH + && standard_sse_constant_p (operands[1])))) || memory_operand (operands[0], SFmode))" { switch (which_alternative) @@ -3439,11 +3220,10 @@ case 3: case 4: return "mov{l}\t{%1, %0|%0, %1}"; + case 5: - if (get_attr_mode (insn) == MODE_TI) - return "%vpxor\t%0, %d0"; - else - return "%vxorps\t%0, %d0"; + return standard_sse_constant_opcode (insn, operands[1]); + case 6: if (get_attr_mode (insn) == MODE_V4SF) return "%vmovaps\t{%1, %0|%0, %1}"; @@ -3535,7 +3315,7 @@ } else if (FP_REG_P (r)) { - if (!standard_80387_constant_p (c)) + if (standard_80387_constant_p (c) < 1) FAIL; } else if (MMX_REG_P (r)) @@ -3567,7 +3347,7 @@ } else if (FP_REG_P (r)) { - if (!standard_80387_constant_p (c)) + if (standard_80387_constant_p (c) < 1) FAIL; } else if (MMX_REG_P (r)) @@ -4698,7 +4478,7 @@ && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && (TARGET_64BIT || <MODE>mode != DImode)) && TARGET_SSE_MATH)" - "* return output_fix_trunc (insn, operands, 1);" + "* return output_fix_trunc (insn, operands, true);" [(set_attr "type" "fisttp") (set_attr "mode" "<MODE>")]) @@ -4782,7 +4562,7 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && !TARGET_FISTTP && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "trunc") (set_attr "mode" "DI")]) @@ -4837,7 +4617,7 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && !TARGET_FISTTP && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "trunc") (set_attr "mode" "<MODE>")]) @@ -11284,56 +11064,134 @@ ;; P6 processors will jump to the address after the decrement when %esp ;; is used as a call operand, so they will execute return address as a code. ;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17. - + +;; Register constraint for call instruction. +(define_mode_attr c [(SI "l") (DI "r")]) + ;; Call subroutine returning no value. -(define_expand "call_pop" - [(parallel [(call (match_operand:QI 0 "" "") - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "" "")))])] - "!TARGET_64BIT" +(define_expand "call" + [(call (match_operand:QI 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))] + "" +{ + ix86_expand_call (NULL, operands[0], operands[1], + operands[2], NULL, false); + DONE; +}) + +(define_expand "sibcall" + [(call (match_operand:QI 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))] + "" { ix86_expand_call (NULL, operands[0], operands[1], - operands[2], operands[3], 0); + operands[2], NULL, true); DONE; }) -(define_insn_and_split "*call_pop_0_vzeroupper" +(define_insn_and_split "*call_vzeroupper" + [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zm")) + (match_operand 1 "" "")) + (unspec [(match_operand 2 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && !SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" + [(set_attr "type" "call")]) + +(define_insn "*call" + [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zm")) + (match_operand 1 "" ""))] + "!SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[0]);" + [(set_attr "type" "call")]) + +(define_insn_and_split "*call_rex64_ms_sysv_vzeroupper" [(parallel - [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" "")) - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "")))]) - (unspec [(match_operand 3 "const_int_operand" "")] + [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzm")) + (match_operand 1 "" "")) + (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) + (clobber (reg:TI XMM6_REG)) + (clobber (reg:TI XMM7_REG)) + (clobber (reg:TI XMM8_REG)) + (clobber (reg:TI XMM9_REG)) + (clobber (reg:TI XMM10_REG)) + (clobber (reg:TI XMM11_REG)) + (clobber (reg:TI XMM12_REG)) + (clobber (reg:TI XMM13_REG)) + (clobber (reg:TI XMM14_REG)) + (clobber (reg:TI XMM15_REG)) + (clobber (reg:DI SI_REG)) + (clobber (reg:DI DI_REG))]) + (unspec [(match_operand 2 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT" + "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" [(set_attr "type" "call")]) -(define_insn "*call_pop_0" - [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" "")) - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "")))] +(define_insn "*call_rex64_ms_sysv" + [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzm")) + (match_operand 1 "" "")) + (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) + (clobber (reg:TI XMM6_REG)) + (clobber (reg:TI XMM7_REG)) + (clobber (reg:TI XMM8_REG)) + (clobber (reg:TI XMM9_REG)) + (clobber (reg:TI XMM10_REG)) + (clobber (reg:TI XMM11_REG)) + (clobber (reg:TI XMM12_REG)) + (clobber (reg:TI XMM13_REG)) + (clobber (reg:TI XMM14_REG)) + (clobber (reg:TI XMM15_REG)) + (clobber (reg:DI SI_REG)) + (clobber (reg:DI DI_REG))] + "TARGET_64BIT && !SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[0]);" + [(set_attr "type" "call")]) + +(define_insn_and_split "*sibcall_vzeroupper" + [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) + (unspec [(match_operand 2 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" + [(set_attr "type" "call")]) + +(define_insn "*sibcall" + [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" ""))] + "SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[0]);" + [(set_attr "type" "call")]) + +(define_expand "call_pop" + [(parallel [(call (match_operand:QI 0 "" "") + (match_operand:SI 1 "" "")) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "" "")))])] "!TARGET_64BIT" { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P0"; - else - return "call\t%P0"; -} - [(set_attr "type" "call")]) + ix86_expand_call (NULL, operands[0], operands[1], + operands[2], operands[3], false); + DONE; +}) -(define_insn_and_split "*call_pop_1_vzeroupper" +(define_insn_and_split "*call_pop_vzeroupper" [(parallel - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm")) (match_operand:SI 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) @@ -11347,27 +11205,23 @@ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" [(set_attr "type" "call")]) -(define_insn "*call_pop_1" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) - (match_operand:SI 1 "" "")) +(define_insn "*call_pop" + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm")) + (match_operand 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 2 "immediate_operand" "i")))] "!TARGET_64BIT && !SIBLING_CALL_P (insn)" -{ - if (constant_call_address_operand (operands[0], Pmode)) - return "call\t%P0"; - return "call\t%A0"; -} + "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) -(define_insn_and_split "*sibcall_pop_1_vzeroupper" +(define_insn_and_split "*sibcall_pop_vzeroupper" [(parallel - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand:SI 1 "" "")) + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i,i")))]) + (match_operand:SI 2 "immediate_operand" "i")))]) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" @@ -11377,120 +11231,89 @@ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" [(set_attr "type" "call")]) -(define_insn "*sibcall_pop_1" - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand:SI 1 "" "")) +(define_insn "*sibcall_pop" + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i,i")))] + (match_operand:SI 2 "immediate_operand" "i")))] "!TARGET_64BIT && SIBLING_CALL_P (insn)" - "@ - jmp\t%P0 - jmp\t%A0" + "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) -(define_expand "call" - [(call (match_operand:QI 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] +;; Call subroutine, returning value in operand 0 + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "" "") + (match_operand 2 "" ""))) + (use (match_operand 3 "" ""))] "" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, false); DONE; }) -(define_expand "sibcall" - [(call (match_operand:QI 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] +(define_expand "sibcall_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "" "") + (match_operand 2 "" ""))) + (use (match_operand 3 "" ""))] "" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, true); DONE; }) -(define_insn_and_split "*call_0_vzeroupper" - [(call (mem:QI (match_operand 0 "constant_call_address_operand" "")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*call_0" - [(call (mem:QI (match_operand 0 "constant_call_address_operand" "")) - (match_operand 1 "" ""))] - "" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*call_1_vzeroupper" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*call_1" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) - (match_operand 1 "" ""))] - "!TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*sibcall_1_vzeroupper" - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] +(define_insn_and_split "*call_value_vzeroupper" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zm")) + (match_operand 2 "" ""))) + (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" + "TARGET_VZEROUPPER && !SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) + "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + [(set_attr "type" "callv")]) -(define_insn "*sibcall_1" - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" ""))] - "!TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) +(define_insn "*call_value" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zm")) + (match_operand 2 "" "")))] + "!SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -(define_insn_and_split "*call_1_rex64_vzeroupper" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] +(define_insn_and_split "*sibcall_value_vzeroupper" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" + "TARGET_VZEROUPPER && SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) + "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + [(set_attr "type" "callv")]) -(define_insn "*call_1_rex64" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" ""))] - "TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) +(define_insn "*sibcall_value" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" "")))] + "SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -(define_insn_and_split "*call_1_rex64_ms_sysv_vzeroupper" +(define_insn_and_split "*call_value_rex64_ms_sysv_vzeroupper" [(parallel - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" "")) + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzm")) + (match_operand 2 "" ""))) (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) (clobber (reg:TI XMM6_REG)) (clobber (reg:TI XMM7_REG)) @@ -11504,18 +11327,19 @@ (clobber (reg:TI XMM15_REG)) (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))]) - (unspec [(match_operand 2 "const_int_operand" "")] + (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) + "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + [(set_attr "type" "callv")]) -(define_insn "*call_1_rex64_ms_sysv" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" "")) +(define_insn "*call_value_rex64_ms_sysv" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzm")) + (match_operand 2 "" ""))) (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) (clobber (reg:TI XMM6_REG)) (clobber (reg:TI XMM7_REG)) @@ -11530,48 +11354,9 @@ (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))] "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*call_1_rex64_large_vzeroupper" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*call_1_rex64_large" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm")) - (match_operand 1 "" ""))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*sibcall_1_rex64_vzeroupper" - [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*sibcall_1_rex64" - [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" ""))] - "TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -;; Call subroutine, returning value in operand 0 (define_expand "call_value_pop" [(parallel [(set (match_operand 0 "" "") (call (match_operand:QI 1 "" "") @@ -11582,35 +11367,65 @@ "!TARGET_64BIT" { ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], operands[4], 0); + operands[3], operands[4], false); DONE; }) -(define_expand "call_value" +(define_insn_and_split "*call_value_pop_vzeroupper" + [(parallel + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))]) + (unspec [(match_operand 4 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" + [(set_attr "type" "callv")]) + +(define_insn "*call_value_pop" [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "" "") - (match_operand:SI 2 "" ""))) - (use (match_operand:SI 3 "" ""))] - ;; Operand 3 is not used on the i386. - "" -{ - ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], NULL, 0); - DONE; -}) + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))] + "!TARGET_64BIT && !SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -(define_expand "sibcall_value" +(define_insn_and_split "*sibcall_value_pop_vzeroupper" + [(parallel + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))]) + (unspec [(match_operand 4 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" + [(set_attr "type" "callv")]) + +(define_insn "*sibcall_value_pop" [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "" "") - (match_operand:SI 2 "" ""))) - (use (match_operand:SI 3 "" ""))] - ;; Operand 3 is not used on the i386. - "" -{ - ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], NULL, 1); - DONE; -}) + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))] + "!TARGET_64BIT && SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) ;; Call subroutine returning any type. @@ -11640,7 +11455,7 @@ : X86_64_MS_SSE_REGPARM_MAX) : X86_32_SSE_REGPARM_MAX) - 1), - NULL, 0); + NULL, false); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -12540,164 +12355,144 @@ (define_insn "*tls_global_dynamic_32_gnu" [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "tls_symbolic_operand" "") - (match_operand:SI 3 "call_insn_operand" "")] - UNSPEC_TLS_GD)) + (unspec:SI + [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "tls_symbolic_operand" "") + (match_operand:SI 3 "constant_call_address_operand" "z")] + UNSPEC_TLS_GD)) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" - "lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}\;call\t%P3" +{ + output_asm_insn + ("lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}", operands); + return "call\t%P3"; +} [(set_attr "type" "multi") (set_attr "length" "12")]) (define_expand "tls_global_dynamic_32" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (unspec:SI - [(match_dup 2) - (match_operand:SI 1 "tls_symbolic_operand" "") - (match_dup 3)] - UNSPEC_TLS_GD)) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (reg:CC FLAGS_REG))])] - "" -{ - if (flag_pic) - operands[2] = pic_offset_table_rtx; - else - { - operands[2] = gen_reg_rtx (Pmode); - emit_insn (gen_set_got (operands[2])); - } - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_32 - (operands[0], operands[1], operands[2])); - DONE; - } - operands[3] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 1 "tls_symbolic_operand" "") + (match_operand:SI 3 "constant_call_address_operand" "")] + UNSPEC_TLS_GD)) + (clobber (match_scratch:SI 4 "")) + (clobber (match_scratch:SI 5 "")) + (clobber (reg:CC FLAGS_REG))])]) (define_insn "*tls_global_dynamic_64" [(set (match_operand:DI 0 "register_operand" "=a") - (call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" "")) - (match_operand:DI 3 "" ""))) + (call:DI + (mem:QI (match_operand:DI 2 "constant_call_address_operand" "z")) + (match_operand:DI 3 "" ""))) (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" - { return ASM_BYTE "0x66\n\tlea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}\n" ASM_SHORT "0x6666\n\trex64\n\tcall\t%P2"; } +{ + fputs (ASM_BYTE "0x66\n", asm_out_file); + output_asm_insn + ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands); + fputs (ASM_SHORT "0x6666\n", asm_out_file); + fputs ("\trex64\n", asm_out_file); + return "call\t%P2"; +} [(set_attr "type" "multi") (set_attr "length" "16")]) (define_expand "tls_global_dynamic_64" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (call:DI (mem:QI (match_dup 2)) (const_int 0))) - (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] - UNSPEC_TLS_GD)])] - "" -{ - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_64 - (operands[0], operands[1])); - DONE; - } - operands[2] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (call:DI + (mem:QI (match_operand:DI 2 "constant_call_address_operand" "")) + (const_int 0))) + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLS_GD)])]) (define_insn "*tls_local_dynamic_base_32_gnu" [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "call_insn_operand" "")] - UNSPEC_TLS_LD_BASE)) + (unspec:SI + [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "constant_call_address_operand" "z")] + UNSPEC_TLS_LD_BASE)) (clobber (match_scratch:SI 3 "=d")) (clobber (match_scratch:SI 4 "=c")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" - "lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}\;call\t%P2" +{ + output_asm_insn + ("lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}", operands); + return "call\t%P2"; +} [(set_attr "type" "multi") (set_attr "length" "11")]) (define_expand "tls_local_dynamic_base_32" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (unspec:SI [(match_dup 1) (match_dup 2)] - UNSPEC_TLS_LD_BASE)) - (clobber (match_scratch:SI 3 "")) - (clobber (match_scratch:SI 4 "")) - (clobber (reg:CC FLAGS_REG))])] - "" -{ - if (flag_pic) - operands[1] = pic_offset_table_rtx; - else - { - operands[1] = gen_reg_rtx (Pmode); - emit_insn (gen_set_got (operands[1])); - } - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_32 - (operands[0], ix86_tls_module_base (), operands[1])); - DONE; - } - operands[2] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "constant_call_address_operand" "")] + UNSPEC_TLS_LD_BASE)) + (clobber (match_scratch:SI 3 "")) + (clobber (match_scratch:SI 4 "")) + (clobber (reg:CC FLAGS_REG))])]) (define_insn "*tls_local_dynamic_base_64" [(set (match_operand:DI 0 "register_operand" "=a") - (call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" "")) - (match_operand:DI 2 "" ""))) + (call:DI + (mem:QI (match_operand:DI 1 "constant_call_address_operand" "z")) + (match_operand:DI 2 "" ""))) (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)] "TARGET_64BIT" - "lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}\;call\t%P1" +{ + output_asm_insn + ("lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}", operands); + return "call\t%P1"; +} [(set_attr "type" "multi") (set_attr "length" "12")]) (define_expand "tls_local_dynamic_base_64" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (call:DI (mem:QI (match_dup 1)) (const_int 0))) - (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])] - "" -{ - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_64 - (operands[0], ix86_tls_module_base ())); - DONE; - } - operands[1] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (call:DI + (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) + (const_int 0))) + (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]) ;; Local dynamic of a single variable is a lose. Show combine how ;; to convert that back to global dynamic. (define_insn_and_split "*tls_local_dynamic_32_once" [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "call_insn_operand" "")] - UNSPEC_TLS_LD_BASE) - (const:SI (unspec:SI - [(match_operand:SI 3 "tls_symbolic_operand" "")] - UNSPEC_DTPOFF)))) + (plus:SI + (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "constant_call_address_operand" "z")] + UNSPEC_TLS_LD_BASE) + (const:SI (unspec:SI + [(match_operand:SI 3 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) (clobber (reg:CC FLAGS_REG))] "" "#" "" - [(parallel [(set (match_dup 0) - (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)] - UNSPEC_TLS_GD)) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (reg:CC FLAGS_REG))])]) + [(parallel + [(set (match_dup 0) + (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)] + UNSPEC_TLS_GD)) + (clobber (match_dup 4)) + (clobber (match_dup 5)) + (clobber (reg:CC FLAGS_REG))])]) ;; Segment register for the thread base ptr load (define_mode_attr tp_seg [(SI "gs") (DI "fs")]) -;; Load and add the thread base pointer from %gs:0. +;; Load and add the thread base pointer from %<tp_seg>:0. (define_insn "*load_tp_<mode>" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P [(const_int 0)] UNSPEC_TP))] @@ -12731,7 +12526,11 @@ UNSPEC_TLS_IE_SUN)) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && TARGET_SUN_TLS" - "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}\n\tadd{q}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}" +{ + output_asm_insn + ("mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}", operands); + return "add{q}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}"; +} [(set_attr "type" "multi")]) ;; GNU2 TLS patterns can be split. @@ -13574,7 +13373,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]) (define_split @@ -13584,7 +13383,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]) (define_insn "sincos_extend<mode>xf3_i387" @@ -13610,7 +13409,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 1) (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SIN))]) @@ -13622,7 +13421,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 0) (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_COS))]) @@ -14594,7 +14393,7 @@ UNSPEC_FIST)) (clobber (match_scratch:XF 2 "=&1f"))] "TARGET_USE_FANCY_MATH_387" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fpspc") (set_attr "mode" "DI")]) @@ -14653,7 +14452,7 @@ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] UNSPEC_FIST))] "TARGET_USE_FANCY_MATH_387" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fpspc") (set_attr "mode" "<MODE>")]) @@ -14843,7 +14642,7 @@ (clobber (match_scratch:XF 4 "=&1f"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "floor") (set_attr "mode" "DI")]) @@ -14900,7 +14699,7 @@ (use (match_operand:HI 3 "memory_operand" "m"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "floor") (set_attr "mode" "<MODE>")]) @@ -15100,7 +14899,7 @@ (clobber (match_scratch:XF 4 "=&1f"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "ceil") (set_attr "mode" "DI")]) @@ -15157,7 +14956,7 @@ (use (match_operand:HI 3 "memory_operand" "m"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "ceil") (set_attr "mode" "<MODE>")]) @@ -17429,338 +17228,6 @@ operands[0] = dest; }) -;; Call-value patterns last so that the wildcard operand does not -;; disrupt insn-recog's switch tables. - -(define_insn_and_split "*call_value_pop_0_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "")))]) - (unspec [(match_operand 4 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_pop_0" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "")))] - "!TARGET_64BIT" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_pop_1_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))]) - (unspec [(match_operand 4 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_pop_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))] - "!TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*sibcall_value_pop_1_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i,i")))]) - (unspec [(match_operand 4 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*sibcall_value_pop_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i,i")))] - "!TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_0_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_0" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" "")))] - "!TARGET_64BIT" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_0_rex64_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_0_rex64" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" "")))] - "TARGET_64BIT" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_0_rex64_ms_sysv_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))]) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_0_rex64_ms_sysv" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" "")))] - "!TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*sibcall_value_1_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*sibcall_value_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" "")))] - "!TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_rex64_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1_rex64" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" "")))] - "TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_rex64_ms_sysv_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))]) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1_rex64_ms_sysv" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_rex64_large_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm")) - (match_operand:DI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1_rex64_large" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm")) - (match_operand:DI 2 "" "")))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*sibcall_value_1_rex64_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U")) - (match_operand:DI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*sibcall_value_1_rex64" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U")) - (match_operand:DI 2 "" "")))] - "TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - ;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5. ;; That, however, is usually mapped by the OS to SIGSEGV, which is often ;; caught for use by garbage collectors and the like. Using an insn that diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index f63a40629e1..21e0def1549 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -19,6 +19,9 @@ ; along with GCC; see the file COPYING3. If not see ; <http://www.gnu.org/licenses/>. +HeaderInclude +config/i386/i386-opts.h + ; Bit flags that specify the ISA we are compiling for. Variable int ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAULT @@ -37,10 +40,6 @@ unsigned char arch TargetSave unsigned char tune -;; -mfpath= -TargetSave -unsigned char fpmath - ;; CPU schedule model TargetSave unsigned char schedule @@ -87,15 +86,15 @@ Target Report Mask(ALIGN_DOUBLE) Save Align some doubles on dword boundary malign-functions= -Target RejectNegative Joined Var(ix86_align_funcs_string) +Target RejectNegative Joined UInteger Function starts are aligned to this power of 2 malign-jumps= -Target RejectNegative Joined Var(ix86_align_jumps_string) +Target RejectNegative Joined UInteger Jump targets are aligned to this power of 2 malign-loops= -Target RejectNegative Joined Var(ix86_align_loops_string) +Target RejectNegative Joined UInteger Loop code aligned to this power of 2 malign-stringops @@ -107,21 +106,50 @@ Target RejectNegative Joined Var(ix86_arch_string) Generate code for given CPU masm= -Target RejectNegative Joined Var(ix86_asm_string) +Target RejectNegative Joined Enum(asm_dialect) Var(ix86_asm_dialect) Init(ASM_ATT) Use given assembler dialect +Enum +Name(asm_dialect) Type(enum asm_dialect) +Known assembler dialects (for use with the -masm-dialect= option): + +EnumValue +Enum(asm_dialect) String(intel) Value(ASM_INTEL) + +EnumValue +Enum(asm_dialect) String(att) Value(ASM_ATT) + mbranch-cost= -Target RejectNegative Joined Var(ix86_branch_cost_string) +Target RejectNegative Joined UInteger Var(ix86_branch_cost) Branches are this expensive (1-5, arbitrary units) mlarge-data-threshold= -Target RejectNegative Joined Var(ix86_section_threshold_string) +Target RejectNegative Joined UInteger Var(ix86_section_threshold) Init(65536) Data greater than given threshold will go into .ldata section in x86-64 medium model mcmodel= -Target RejectNegative Joined Var(ix86_cmodel_string) +Target RejectNegative Joined Enum(cmodel) Var(ix86_cmodel) Init(CM_32) Use given x86-64 code model +Enum +Name(cmodel) Type(enum cmodel) +Known code models (for use with the -mcmodel= option): + +EnumValue +Enum(cmodel) String(small) Value(CM_SMALL) + +EnumValue +Enum(cmodel) String(medium) Value(CM_MEDIUM) + +EnumValue +Enum(cmodel) String(large) Value(CM_LARGE) + +EnumValue +Enum(cmodel) String(32) Value(CM_32) + +EnumValue +Enum(cmodel) String(kernel) Value(CM_KERNEL) + mcpu= Target RejectNegative Joined Undocumented Alias(mtune=) Warn(%<-mcpu=%> is deprecated; use %<-mtune=%> or %<-march=%> instead) @@ -138,9 +166,34 @@ Target Report Mask(FLOAT_RETURNS) Save Return values of functions in FPU registers mfpmath= -Target RejectNegative Joined Var(ix86_fpmath_string) +Target RejectNegative Joined Var(ix86_fpmath) Enum(fpmath_unit) Init(FPMATH_387) Save Generate floating point mathematics using given instruction set +Enum +Name(fpmath_unit) Type(enum fpmath_unit) +Valid arguments to -mfpmath=: + +EnumValue +Enum(fpmath_unit) String(387) Value(FPMATH_387) + +EnumValue +Enum(fpmath_unit) String(sse) Value(FPMATH_SSE) + +EnumValue +Enum(fpmath_unit) String(387,sse) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)}) + +EnumValue +Enum(fpmath_unit) String(387+sse) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)}) + +EnumValue +Enum(fpmath_unit) String(sse,387) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)}) + +EnumValue +Enum(fpmath_unit) String(sse+387) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)}) + +EnumValue +Enum(fpmath_unit) String(both) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)}) + mhard-float Target RejectNegative Mask(80387) MaskExists Save Use hardware fp @@ -181,16 +234,24 @@ momit-leaf-frame-pointer Target Report Mask(OMIT_LEAF_FRAME_POINTER) Save Omit the frame pointer in leaf functions -mpc -Target RejectNegative Report Joined Var(ix87_precision_string) -Set 80387 floating-point precision (-mpc32, -mpc64, -mpc80) +mpc32 +Target RejectNegative Report +Set 80387 floating-point precision to 32-bit + +mpc64 +Target RejectNegative Report +Set 80387 floating-point precision to 64-bit + +mpc80 +Target RejectNegative Report +Set 80387 floating-point precision to 80-bit mpreferred-stack-boundary= -Target RejectNegative Joined Var(ix86_preferred_stack_boundary_string) +Target RejectNegative Joined UInteger Var(ix86_preferred_stack_boundary_arg) Attempt to keep stack aligned to this power of 2 mincoming-stack-boundary= -Target RejectNegative Joined Var(ix86_incoming_stack_boundary_string) +Target RejectNegative Joined UInteger Var(ix86_incoming_stack_boundary_arg) Assume incoming stack aligned to this power of 2 mpush-args @@ -202,7 +263,7 @@ Target RejectNegative Report InverseMask(NO_RED_ZONE, RED_ZONE) Save Use red-zone in the x86-64 code mregparm= -Target RejectNegative Joined Var(ix86_regparm_string) +Target RejectNegative Joined UInteger Var(ix86_regparm) Number of registers used to pass integer arguments mrtd @@ -226,13 +287,48 @@ Target Report Mask(STACK_PROBE) Save Enable stack probing mstringop-strategy= -Target RejectNegative Joined Var(ix86_stringop_string) +Target RejectNegative Joined Enum(stringop_alg) Var(ix86_stringop_alg) Init(no_stringop) Chose strategy to generate stringop using +Enum +Name(stringop_alg) Type(enum stringop_alg) +Valid arguments to -mstringop-strategy=: + +EnumValue +Enum(stringop_alg) String(rep_byte) Value(rep_prefix_1_byte) + +EnumValue +Enum(stringop_alg) String(libcall) Value(libcall) + +EnumValue +Enum(stringop_alg) String(rep_4byte) Value(rep_prefix_4_byte) + +EnumValue +Enum(stringop_alg) String(rep_8byte) Value(rep_prefix_8_byte) + +EnumValue +Enum(stringop_alg) String(byte_loop) Value(loop_1_byte) + +EnumValue +Enum(stringop_alg) String(loop) Value(loop) + +EnumValue +Enum(stringop_alg) String(unrolled_loop) Value(unrolled_loop) + mtls-dialect= -Target RejectNegative Joined Var(ix86_tls_dialect_string) +Target RejectNegative Joined Var(ix86_tls_dialect) Enum(tls_dialect) Init(TLS_DIALECT_GNU) Use given thread-local storage dialect +Enum +Name(tls_dialect) Type(enum tls_dialect) +Known TLS dialects (for use with the -mtls-dialect= option): + +EnumValue +Enum(tls_dialect) String(gnu) Value(TLS_DIALECT_GNU) + +EnumValue +Enum(tls_dialect) String(gnu2) Value(TLS_DIALECT_GNU2) + mtls-direct-seg-refs Target Report Mask(TLS_DIRECT_SEG_REFS) Use direct references against %gs when accessing tls data @@ -242,13 +338,33 @@ Target RejectNegative Joined Var(ix86_tune_string) Schedule code for given CPU mabi= -Target RejectNegative Joined Var(ix86_abi_string) +Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI) Generate code that conforms to the given ABI +Enum +Name(calling_abi) Type(enum calling_abi) +Known ABIs (for use with the -mabi= option): + +EnumValue +Enum(calling_abi) String(sysv) Value(SYSV_ABI) + +EnumValue +Enum(calling_abi) String(ms) Value(MS_ABI) + mveclibabi= -Target RejectNegative Joined Var(ix86_veclibabi_string) +Target RejectNegative Joined Var(ix86_veclibabi_type) Enum(ix86_veclibabi) Init(ix86_veclibabi_type_none) Vector library ABI to use +Enum +Name(ix86_veclibabi) Type(enum ix86_veclibabi) +Known vectorization library ABIs (for use with the -mveclibabi= option): + +EnumValue +Enum(ix86_veclibabi) String(svml) Value(ix86_veclibabi_type_svml) + +EnumValue +Enum(ix86_veclibabi) String(acml) Value(ix86_veclibabi_type_acml) + mvect8-ret-in-mem Target Report Mask(VECT8_RETURNS) Save Return 8-byte vectors in memory diff --git a/gcc/config/i386/sol2-10.h b/gcc/config/i386/sol2-10.h index c3decd2ef24..04a7132dc6c 100644 --- a/gcc/config/i386/sol2-10.h +++ b/gcc/config/i386/sol2-10.h @@ -133,6 +133,3 @@ along with GCC; see the file COPYING3. If not see /* We do not need to search a special directory for startup files. */ #undef MD_STARTFILE_PREFIX - -#undef TARGET_ASM_NAMED_SECTION -#define TARGET_ASM_NAMED_SECTION i386_solaris_elf_named_section diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h index baddbb0b929..36ca62f904c 100644 --- a/gcc/config/i386/sol2.h +++ b/gcc/config/i386/sol2.h @@ -154,6 +154,9 @@ along with GCC; see the file COPYING3. If not see } \ while (0) +#undef TARGET_ASM_NAMED_SECTION +#define TARGET_ASM_NAMED_SECTION i386_solaris_elf_named_section + /* We do not need NT_VERSION notes. */ #undef X86_FILE_START_VERSION_DIRECTIVE #define X86_FILE_START_VERSION_DIRECTIVE false diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 291bffb636e..ddd66fd83b7 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -1663,7 +1663,7 @@ (match_operand:VF 3 "nonimmediate_operand" "xm,x")] UNSPEC_FMADDSUB))] "TARGET_FMA4" - "vfmaddsubps\t{%3, %2, %1, %0|%0, %1, %2, %3}" + "vfmaddsub<ssemodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ssemuladd") (set_attr "mode" "<MODE>")]) @@ -1676,7 +1676,7 @@ (match_operand:VF 3 "nonimmediate_operand" "xm,x"))] UNSPEC_FMADDSUB))] "TARGET_FMA4" - "vfmsubaddps\t{%3, %2, %1, %0|%0, %1, %2, %3}" + "vfmsubadd<ssemodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ssemuladd") (set_attr "mode" "<MODE>")]) @@ -10294,12 +10294,13 @@ "&& reload_completed" [(const_int 0)] { + rtx op0 = operands[0]; rtx op1 = operands[1]; - if (REG_P (op1)) + if (REG_P (op0)) + op0 = gen_rtx_REG (<ssehalfvecmode>mode, REGNO (op0)); + else op1 = gen_rtx_REG (<MODE>mode, REGNO (op1)); - else - op1 = gen_lowpart (<MODE>mode, op1); - emit_move_insn (operands[0], op1); + emit_move_insn (op0, op1); DONE; }) diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index 22f36487579..20378d090bf 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -1,5 +1,5 @@ ;; GCC machine description for i386 synchronization instructions. -;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 +;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 ;; Free Software Foundation, Inc. ;; ;; This file is part of GCC. @@ -164,17 +164,74 @@ "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic" "xchg{l}\t%%ebx, %3\;lock{%;} cmpxchg8b\t%1\;xchg{l}\t%%ebx, %3") +;; For operand 2 nonmemory_operand predicate is used instead of +;; register_operand to allow combiner to better optimize atomic +;; additions of constants. (define_insn "sync_old_add<mode>" [(set (match_operand:SWI 0 "register_operand" "=<r>") (unspec_volatile:SWI [(match_operand:SWI 1 "memory_operand" "+m")] UNSPECV_XCHG)) (set (match_dup 1) (plus:SWI (match_dup 1) - (match_operand:SWI 2 "register_operand" "0"))) + (match_operand:SWI 2 "nonmemory_operand" "0"))) (clobber (reg:CC FLAGS_REG))] "TARGET_XADD" "lock{%;} xadd{<imodesuffix>}\t{%0, %1|%1, %0}") +;; This peephole2 and following insn optimize +;; __sync_fetch_and_add (x, -N) == N into just lock {add,sub,inc,dec} +;; followed by testing of flags instead of lock xadd and comparisons. +(define_peephole2 + [(set (match_operand:SWI 0 "register_operand" "") + (match_operand:SWI 2 "const_int_operand" "")) + (parallel [(set (match_dup 0) + (unspec_volatile:SWI + [(match_operand:SWI 1 "memory_operand" "")] UNSPECV_XCHG)) + (set (match_dup 1) + (plus:SWI (match_dup 1) + (match_dup 0))) + (clobber (reg:CC FLAGS_REG))]) + (set (reg:CCZ FLAGS_REG) + (compare:CCZ (match_dup 0) + (match_operand:SWI 3 "const_int_operand" "")))] + "peep2_reg_dead_p (3, operands[0]) + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) + == -(unsigned HOST_WIDE_INT) INTVAL (operands[3]) + && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(parallel [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (unspec_volatile:SWI [(match_dup 1)] + UNSPECV_XCHG) + (match_dup 3))) + (set (match_dup 1) + (plus:SWI (match_dup 1) + (match_dup 2)))])]) + +(define_insn "*sync_old_add_cmp<mode>" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (unspec_volatile:SWI + [(match_operand:SWI 0 "memory_operand" "+m")] + UNSPECV_XCHG) + (match_operand:SWI 2 "const_int_operand" "i"))) + (set (match_dup 0) + (plus:SWI (match_dup 0) + (match_operand:SWI 1 "const_int_operand" "i")))] + "(unsigned HOST_WIDE_INT) INTVAL (operands[1]) + == -(unsigned HOST_WIDE_INT) INTVAL (operands[2])" +{ + if (TARGET_USE_INCDEC) + { + if (operands[1] == const1_rtx) + return "lock{%;} inc{<imodesuffix>}\t%0"; + if (operands[1] == constm1_rtx) + return "lock{%;} dec{<imodesuffix>}\t%0"; + } + + if (x86_maybe_negate_const_int (&operands[1], <MODE>mode)) + return "lock{%;} sub{<imodesuffix>}\t{%1, %0|%0, %1}"; + + return "lock{%;} add{<imodesuffix>}\t{%1, %0|%0, %1}"; +}) + ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space. (define_insn "sync_lock_test_and_set<mode>" [(set (match_operand:SWI 0 "register_operand" "=<r>") diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386 index e9fa3cd8d6f..a43843351a0 100644 --- a/gcc/config/i386/t-i386 +++ b/gcc/config/i386/t-i386 @@ -24,7 +24,7 @@ i386.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \ $(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \ i386-builtin-types.inc debug.h dwarf2out.h sbitmap.h $(FIBHEAP_H) \ - $(OPTS_H) + $(OPTS_H) $(DIAGNOSTIC_H) i386-c.o: $(srcdir)/config/i386/i386-c.c \ $(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \ diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 331f0c18dcc..f293579f5a5 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -15287,7 +15287,6 @@ mips_handle_option (struct gcc_options *opts, location_t loc ATTRIBUTE_UNUSED) { size_t code = decoded->opt_index; - const char *arg = decoded->arg; switch (code) { diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h index 72cb199ce30..56d69316905 100644 --- a/gcc/config/rx/rx-protos.h +++ b/gcc/config/rx/rx-protos.h @@ -31,7 +31,7 @@ extern void rx_emit_stack_popm (rtx *, bool); extern void rx_emit_stack_pushm (rtx *); extern void rx_expand_epilogue (bool); extern char * rx_gen_move_template (rtx *, bool); -extern bool rx_legitimate_constant_p (enum machine_mode, rtx); +extern bool rx_is_legitimate_constant (enum machine_mode, rtx); extern bool rx_is_restricted_memory_address (rtx, enum machine_mode); extern bool rx_match_ccmode (rtx, enum machine_mode); diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index c8ff4393616..cedb0e073ed 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -58,7 +58,7 @@ static void rx_print_operand (FILE *, rtx, int); #define CC_FLAG_Z (1 << 1) #define CC_FLAG_O (1 << 2) #define CC_FLAG_C (1 << 3) -#define CC_FLAG_FP (1 << 4) /* fake, to differentiate CC_Fmode */ +#define CC_FLAG_FP (1 << 4) /* Fake, to differentiate CC_Fmode. */ static unsigned int flags_from_mode (enum machine_mode mode); static unsigned int flags_from_code (enum rtx_code code); @@ -85,7 +85,9 @@ rx_is_legitimate_address (enum machine_mode mode, rtx x, /* Register Indirect. */ return true; - if (GET_MODE_SIZE (mode) <= 4 + if ((GET_MODE_SIZE (mode) == 4 + || GET_MODE_SIZE (mode) == 2 + || GET_MODE_SIZE (mode) == 1) && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)) /* Pre-decrement Register Indirect or Post-increment Register Indirect. */ @@ -125,7 +127,7 @@ rx_is_legitimate_address (enum machine_mode mode, rtx x, case 1: factor = 1; break; } - if (val >= (0x10000 * factor)) + if (val > (65535 * factor)) return false; return (val % factor) == 0; } @@ -1349,7 +1351,7 @@ gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related) insn = emit_insn (gen_addsi3 (dest, src, val)); else { - /* Wrap VAL in an UNSPEC so that rx_legitimate_constant_p + /* Wrap VAL in an UNSPEC so that rx_is_legitimate_constant will not reject it. */ val = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_CONST)); insn = emit_insn (gen_addsi3 (dest, src, val)); @@ -1928,11 +1930,14 @@ enum rx_builtin RX_BUILTIN_max }; +static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max]; + static void rx_init_builtins (void) { #define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE) \ - add_builtin_function ("__builtin_rx_" LC_NAME, \ + rx_builtins[RX_BUILTIN_##UC_NAME] = \ + add_builtin_function ("__builtin_rx_" LC_NAME, \ build_function_type_list (RET_TYPE##_type_node, \ ARG_TYPE##_type_node, \ NULL_TREE), \ @@ -1940,6 +1945,7 @@ rx_init_builtins (void) BUILT_IN_MD, NULL, NULL_TREE) #define ADD_RX_BUILTIN2(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \ + rx_builtins[RX_BUILTIN_##UC_NAME] = \ add_builtin_function ("__builtin_rx_" LC_NAME, \ build_function_type_list (RET_TYPE##_type_node, \ ARG_TYPE1##_type_node,\ @@ -1949,6 +1955,7 @@ rx_init_builtins (void) BUILT_IN_MD, NULL, NULL_TREE) #define ADD_RX_BUILTIN3(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3) \ + rx_builtins[RX_BUILTIN_##UC_NAME] = \ add_builtin_function ("__builtin_rx_" LC_NAME, \ build_function_type_list (RET_TYPE##_type_node, \ ARG_TYPE1##_type_node,\ @@ -1980,6 +1987,17 @@ rx_init_builtins (void) ADD_RX_BUILTIN1 (WAIT, "wait", void, void); } +/* Return the RX builtin for CODE. */ + +static tree +rx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) +{ + if (code >= RX_BUILTIN_max) + return error_mark_node; + + return rx_builtins[code]; +} + static rtx rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg) { @@ -2448,7 +2466,7 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED) operand on the RX. X is already known to satisfy CONSTANT_P. */ bool -rx_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) +rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) { switch (GET_CODE (x)) { @@ -2620,7 +2638,7 @@ rx_trampoline_init (rtx tramp, tree fndecl, rtx chain) static int rx_memory_move_cost (enum machine_mode mode, reg_class_t regclass, bool in) { - return (in ? 2 : 0) + memory_move_secondary_cost (mode, regclass, in); + return (in ? 2 : 0) + REGISTER_MOVE_COST (mode, regclass, regclass); } /* Convert a CC_MODE to the set of flags that it represents. */ @@ -2782,7 +2800,7 @@ rx_align_for_label (rtx lab, int uses_threshold) because the delay due to the inserted NOPs would be greater than the delay due to the misaligned branch. If uses_threshold is zero then the alignment is always useful. */ - if (LABEL_NUSES (lab) < uses_threshold) + if (LABEL_P (lab) && LABEL_NUSES (lab) < uses_threshold) return 0; return optimize_size ? 1 : 3; @@ -2837,7 +2855,7 @@ rx_adjust_insn_length (rtx insn, int current_length) case CODE_FOR_smaxsi3_zero_extendhi: case CODE_FOR_sminsi3_zero_extendhi: case CODE_FOR_multsi3_zero_extendhi: - case CODE_FOR_comparesi3_zero_extendqi: + case CODE_FOR_comparesi3_zero_extendhi: zero = true; factor = 2; break; @@ -2852,7 +2870,7 @@ rx_adjust_insn_length (rtx insn, int current_length) case CODE_FOR_smaxsi3_sign_extendhi: case CODE_FOR_sminsi3_sign_extendhi: case CODE_FOR_multsi3_sign_extendhi: - case CODE_FOR_comparesi3_zero_extendhi: + case CODE_FOR_comparesi3_sign_extendhi: zero = false; factor = 2; break; @@ -2867,7 +2885,7 @@ rx_adjust_insn_length (rtx insn, int current_length) case CODE_FOR_smaxsi3_zero_extendqi: case CODE_FOR_sminsi3_zero_extendqi: case CODE_FOR_multsi3_zero_extendqi: - case CODE_FOR_comparesi3_sign_extendqi: + case CODE_FOR_comparesi3_zero_extendqi: zero = true; factor = 1; break; @@ -2882,7 +2900,7 @@ rx_adjust_insn_length (rtx insn, int current_length) case CODE_FOR_smaxsi3_sign_extendqi: case CODE_FOR_sminsi3_sign_extendqi: case CODE_FOR_multsi3_sign_extendqi: - case CODE_FOR_comparesi3_sign_extendhi: + case CODE_FOR_comparesi3_sign_extendqi: zero = false; factor = 1; break; @@ -2953,6 +2971,9 @@ rx_adjust_insn_length (rtx insn, int current_length) #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS rx_init_builtins +#undef TARGET_BUILTIN_DECL +#define TARGET_BUILTIN_DECL rx_builtin_decl + #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN rx_expand_builtin @@ -3062,8 +3083,8 @@ rx_adjust_insn_length (rtx insn, int current_length) #define TARGET_FLAGS_REGNUM CC_REG #undef TARGET_LEGITIMATE_CONSTANT_P -#define TARGET_LEGITIMATE_CONSTANT_P rx_legitimate_constant_p +#define TARGET_LEGITIMATE_CONSTANT_P rx_is_legitimate_constant struct gcc_target targetm = TARGET_INITIALIZER; -/* #include "gt-rx.h" */ +#include "gt-rx.h" diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index 1780867dcbf..67e8ce1c577 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -144,7 +144,7 @@ #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 -#define HAVE_PRE_DECCREMENT 1 +#define HAVE_PRE_DECREMENT 1 #define HAVE_POST_INCREMENT 1 #define MOVE_RATIO(SPEED) ((SPEED) ? 4 : 2) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 824d246cb84..070f248bbdf 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -556,7 +556,7 @@ if (MEM_P (operand0) && MEM_P (operand1)) operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1); if (CONST_INT_P (operand1) - && ! rx_legitimate_constant_p (<register_modes:MODE>mode, operand1)) + && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1)) FAIL; } ) @@ -904,6 +904,39 @@ (set_attr "length" "3,4,5,6,7,6")] ) +;; Peepholes to match: +;; (set (reg A) (reg B)) +;; (set (CC) (compare:CC (reg A/reg B) (const_int 0))) +;; and replace them with the addsi3_flags pattern, using an add +;; of zero to copy the register and set the condition code bits. +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand")) + (set (reg:CC CC_REG) + (compare:CC (match_dup 0) + (const_int 0)))] + "" + [(parallel [(set (match_dup 0) + (plus:SI (match_dup 1) (const_int 0))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0)) + (const_int 0)))])] +) + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand")) + (set (reg:CC CC_REG) + (compare:CC (match_dup 1) + (const_int 0)))] + "" + [(parallel [(set (match_dup 0) + (plus:SI (match_dup 1) (const_int 0))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0)) + (const_int 0)))])] +) + (define_expand "adddi3" [(set (match_operand:DI 0 "register_operand") (plus:DI (match_operand:DI 1 "register_operand") @@ -1668,6 +1701,35 @@ (extend_types:SI (match_dup 1))))] ) +;; Convert: +;; (set (reg1) (sign_extend (mem)) +;; (set (reg2) (zero_extend (reg1)) +;; into +;; (set (reg2) (zero_extend (mem))) +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand"))) + (set (match_operand:SI 2 "register_operand") + (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))] + "REGNO (operands[0]) == REGNO (operands[3]) + && (REGNO (operands[0]) == REGNO (operands[2]) + || peep2_regno_dead_p (2, REGNO (operands[0])))" + [(set (match_dup 2) + (zero_extend:SI (match_dup 1)))] +) + +;; Remove the redundant sign extension from: +;; (set (reg) (extend (mem))) +;; (set (reg) (extend (reg))) +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "memory_operand"))) + (set (match_dup 0) + (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))] + "REGNO (operands[0]) == REGNO (operands[2])" + [(set (match_dup 0) (extend_types:SI (match_dup 1)))] +) + (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>" [(set (reg:CC CC_REG) (compare:CC (match_operand:SI 0 "register_operand" "=r") @@ -1769,7 +1831,7 @@ ) (define_insn "*bitset_in_memory" - [(set (match_operand:QI 0 "memory_operand" "+Q") + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (ior:QI (ashift:QI (const_int 1) (match_operand:QI 1 "nonmemory_operand" "ri")) (match_dup 0)))] @@ -1790,7 +1852,7 @@ ) (define_insn "*bitinvert_in_memory" - [(set (match_operand:QI 0 "memory_operand" "+Q") + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (xor:QI (ashift:QI (const_int 1) (match_operand:QI 1 "nonmemory_operand" "ri")) (match_dup 0)))] @@ -1813,7 +1875,7 @@ ) (define_insn "*bitclr_in_memory" - [(set (match_operand:QI 0 "memory_operand" "+Q") + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (and:QI (not:QI (ashift:QI (const_int 1) diff --git a/gcc/config/sol2-protos.h b/gcc/config/sol2-protos.h index 800629aaba1..25753ff610e 100644 --- a/gcc/config/sol2-protos.h +++ b/gcc/config/sol2-protos.h @@ -22,3 +22,5 @@ extern void solaris_insert_attributes (tree, tree *); extern void solaris_register_pragmas (void); extern void solaris_output_init_fini (FILE *, tree); extern void solaris_assemble_visibility (tree, int); +extern void solaris_elf_asm_comdat_section (const char *, unsigned int, tree); +extern void solaris_code_end (void); diff --git a/gcc/config/sol2.c b/gcc/config/sol2.c index decde2fea29..7fed184e14d 100644 --- a/gcc/config/sol2.c +++ b/gcc/config/sol2.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "diagnostic-core.h" #include "ggc.h" +#include "hashtab.h" tree solaris_pending_aligns, solaris_pending_inits, solaris_pending_finis; @@ -106,14 +107,14 @@ solaris_output_init_fini (FILE *file, tree decl) { if (lookup_attribute ("init", DECL_ATTRIBUTES (decl))) { - fprintf (file, PUSHSECTION_FORMAT, ".init"); + fprintf (file, "\t.pushsection\t" SECTION_NAME_FORMAT "\n", ".init"); ASM_OUTPUT_CALL (file, decl); fprintf (file, "\t.popsection\n"); } if (lookup_attribute ("fini", DECL_ATTRIBUTES (decl))) { - fprintf (file, PUSHSECTION_FORMAT, ".fini"); + fprintf (file, "\t.pushsection\t" SECTION_NAME_FORMAT "\n", ".fini"); ASM_OUTPUT_CALL (file, decl); fprintf (file, "\t.popsection\n"); } @@ -155,3 +156,129 @@ solaris_assemble_visibility (tree decl ATTRIBUTE_UNUSED, "in this configuration; ignored"); #endif } + +/* Hash table of group signature symbols. */ + +static htab_t solaris_comdat_htab; + +/* Group section information entry stored in solaris_comdat_htab. */ + +typedef struct comdat_entry +{ + const char *name; + unsigned int flags; + tree decl; + const char *sig; +} comdat_entry; + +/* Helper routines for maintaining solaris_comdat_htab. */ + +static hashval_t +comdat_hash (const void *p) +{ + const comdat_entry *entry = (const comdat_entry *) p; + + return htab_hash_string (entry->sig); +} + +static int +comdat_eq (const void *p1, const void *p2) +{ + const comdat_entry *entry1 = (const comdat_entry *) p1; + const comdat_entry *entry2 = (const comdat_entry *) p2; + + return strcmp (entry1->sig, entry2->sig) == 0; +} + +/* Output assembly to switch to COMDAT group section NAME with attributes + FLAGS and group signature symbol DECL, using Sun as syntax. */ + +void +solaris_elf_asm_comdat_section (const char *name, unsigned int flags, tree decl) +{ + const char *signature; + char *section; + comdat_entry entry, **slot; + + if (TREE_CODE (decl) == IDENTIFIER_NODE) + signature = IDENTIFIER_POINTER (decl); + else + signature = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl)); + + /* Sun as requires group sections to be fragmented, i.e. to have names of + the form <section>%<fragment>. Strictly speaking this is only + necessary to support cc -xF, but is enforced globally in violation of + the ELF gABI. We keep the section names generated by GCC (generally + of the form .text.<signature>) and append %<signature> to pacify as, + despite the redundancy. */ + section = concat (name, "%", signature, NULL); + + /* Clear SECTION_LINKONCE flag so targetm.asm_out.named_section only + emits this as a regular section. Emit section before .group + directive since Sun as treats undeclared sections as @progbits, + which conflicts with .bss* sections which are @nobits. */ + targetm.asm_out.named_section (section, flags & ~SECTION_LINKONCE, decl); + + /* Sun as separates declaration of a group section and of the group + itself, using the .group directive and the #comdat flag. */ + fprintf (asm_out_file, "\t.group\t%s," SECTION_NAME_FORMAT ",#comdat\n", + signature, section); + + /* Unlike GNU as, group signature symbols need to be defined explicitly + for Sun as. With a few exceptions, this is already the case. To + identify the missing ones without changing the affected frontents, + remember the signature symbols and emit those not marked + TREE_SYMBOL_REFERENCED in solaris_code_end. */ + if (solaris_comdat_htab == NULL) + solaris_comdat_htab = htab_create_alloc (37, comdat_hash, comdat_eq, NULL, + xcalloc, free); + + entry.sig = signature; + slot = (comdat_entry **) htab_find_slot (solaris_comdat_htab, &entry, INSERT); + + if (*slot == NULL) + { + *slot = XCNEW (comdat_entry); + /* Remember fragmented section name. */ + (*slot)->name = section; + /* Emit as regular section, .group declaration has already been done. */ + (*slot)->flags = flags & ~SECTION_LINKONCE; + (*slot)->decl = decl; + (*slot)->sig = signature; + } +} + +/* Define unreferenced COMDAT group signature symbol corresponding to SLOT. */ + +static int +solaris_define_comdat_signature (void **slot, void *aux ATTRIBUTE_UNUSED) +{ + comdat_entry *entry = *(comdat_entry **) slot; + tree decl = entry->decl; + + if (TREE_CODE (decl) != IDENTIFIER_NODE) + decl = DECL_COMDAT_GROUP (decl); + + if (!TREE_SYMBOL_REFERENCED (decl)) + { + /* Switch to group section, otherwise Sun as complains + `Group Id symbol defined outside of group'. */ + switch_to_section (get_section (entry->name, entry->flags, entry->decl)); + + ASM_OUTPUT_LABEL (asm_out_file, entry->sig); + } + + /* Continue with scan. */ + return 1; +} + +/* Emit unreferenced COMDAT group signature symbols for Sun as. */ + +void +solaris_code_end (void) +{ + if (solaris_comdat_htab == NULL) + return; + + htab_traverse (solaris_comdat_htab, solaris_define_comdat_signature, NULL); +} diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index 7e42ddb6a4b..f3394fda74d 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -19,6 +19,9 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* We are compiling for Solaris 2 now. */ +#define TARGET_SOLARIS 1 + /* We use stabs-in-elf for debugging, because that is what the native toolchain uses. */ #undef PREFERRED_DEBUGGING_TYPE @@ -257,9 +260,8 @@ __enable_execute_stack (void *addr) \ { "init", 0, 0, true, false, false, NULL, false }, \ { "fini", 0, 0, true, false, false, NULL, false } -/* Solaris/x86 as and gas support the common ELF .section/.pushsection - syntax. */ -#define PUSHSECTION_FORMAT "\t.pushsection\t%s\n" +/* Solaris/x86 as and gas support unquoted section names. */ +#define SECTION_NAME_FORMAT "%s" /* This is how to declare the size of a function. For Solaris, we output any .init or .fini entries here. */ diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index 73355ca8c45..a53b82a8e95 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -188,9 +188,16 @@ along with GCC; see the file COPYING3. If not see #undef TARGET_ASM_NAMED_SECTION #define TARGET_ASM_NAMED_SECTION sparc_solaris_elf_asm_named_section -/* And SPARC non-standard pushsection syntax. */ -#undef PUSHSECTION_FORMAT -#define PUSHSECTION_FORMAT "\t.pushsection\t\"%s\"\n" +/* Emit COMDAT group signature symbols for Sun as. */ +#undef TARGET_ASM_CODE_END +#define TARGET_ASM_CODE_END solaris_code_end + +/* Solaris/SPARC as requires doublequoted section names. While gas + supports that, too, we prefer the standard variant. */ +#ifndef USE_GAS +#undef SECTION_NAME_FORMAT +#define SECTION_NAME_FORMAT "\"%s\"" +#endif /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index a3bab331910..10b35f250e9 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -3110,8 +3110,16 @@ legitimate_pic_operand_p (rtx x) return true; } -/* Return nonzero if ADDR is a valid memory address. - STRICT specifies whether strict register checking applies. */ +#define RTX_OK_FOR_OFFSET_P(X) \ + (CONST_INT_P (X) && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000 - 8) + +#define RTX_OK_FOR_OLO10_P(X) \ + (CONST_INT_P (X) && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8) + +/* Handle the TARGET_LEGITIMATE_ADDRESS_P target hook. + + On SPARC, the actual legitimate addresses must be REG+REG or REG+SMALLINT + ordinarily. This changes a bit when generating PIC. */ static bool sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict) @@ -3706,7 +3714,7 @@ sparc_mode_dependent_address_p (const_rtx addr) rtx op0 = XEXP (addr, 0); rtx op1 = XEXP (addr, 1); if (op0 == pic_offset_table_rtx - && SYMBOLIC_CONST (op1)) + && symbolic_operand (op1, VOIDmode)) return true; } @@ -8529,12 +8537,19 @@ sparc_profile_hook (int labelno) } } +#ifdef TARGET_SOLARIS /* Solaris implementation of TARGET_ASM_NAMED_SECTION. */ static void sparc_solaris_elf_asm_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) { + if (HAVE_COMDAT_GROUP && flags & SECTION_LINKONCE) + { + solaris_elf_asm_comdat_section (name, flags, decl); + return; + } + fprintf (asm_out_file, "\t.section\t\"%s\"", name); if (!(flags & SECTION_DEBUG)) @@ -8550,6 +8565,7 @@ sparc_solaris_elf_asm_named_section (const char *name, unsigned int flags, fputc ('\n', asm_out_file); } +#endif /* TARGET_SOLARIS */ /* We do not allow indirect calls to be optimized into sibling calls. diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 7039fb048b0..ad354e89eca 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1538,41 +1538,6 @@ do { \ addresses which require two reload registers. */ #define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X) - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) \ - (REGNO (X) < 32 \ - || REGNO (X) == FRAME_POINTER_REGNUM \ - || REGNO (X) >= FIRST_PSEUDO_REGISTER) - -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_INDEX_P (X) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif /* Should gcc use [%reg+%lo(xx)+offset] addresses? */ @@ -1582,31 +1547,6 @@ do { \ #define USE_AS_OFFSETABLE_LO10 0 #endif -/* On SPARC, the actual legitimate addresses must be REG+REG or REG+SMALLINT - ordinarily. This changes a bit when generating PIC. The details are - in sparc.c's implementation of TARGET_LEGITIMATE_ADDRESS_P. */ - -#define SYMBOLIC_CONST(X) symbolic_operand (X, VOIDmode) - -#define RTX_OK_FOR_BASE_P(X) \ - ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && REG_OK_FOR_BASE_P (SUBREG_REG (X)))) - -#define RTX_OK_FOR_INDEX_P(X) \ - ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && REG_OK_FOR_INDEX_P (SUBREG_REG (X)))) - -#define RTX_OK_FOR_OFFSET_P(X) \ - (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000 - 8) - -#define RTX_OK_FOR_OLO10_P(X) \ - (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8) - - /* Try a machine-dependent way of reloading an illegitimate address operand. If we find one, push the reload and jump to WIN. This macro is used in only one place: `find_reloads_address' in reload.c. */ diff --git a/gcc/config/t-sol2 b/gcc/config/t-sol2 index 6a76bf1bad8..1604b9e499f 100644 --- a/gcc/config/t-sol2 +++ b/gcc/config/t-sol2 @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2008, 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 2004, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -25,7 +25,7 @@ sol2-c.o: $(srcdir)/config/sol2-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ # Solaris-specific attributes sol2.o: $(srcdir)/config/sol2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - tree.h output.h $(TM_H) $(TM_P_H) $(GGC_H) + tree.h output.h $(TM_H) $(TARGET_H) $(TM_P_H) $(GGC_H) $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/sol2.c |