diff options
Diffstat (limited to 'gcc/config/i386/i386-options.cc')
-rw-r--r-- | gcc/config/i386/i386-options.cc | 384 |
1 files changed, 151 insertions, 233 deletions
diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index 45aa9b4..09cb133 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -259,9 +259,7 @@ static struct ix86_target_opts isa2_opts[] = { "-msm3", OPTION_MASK_ISA2_SM3 }, { "-msha512", OPTION_MASK_ISA2_SHA512 }, { "-msm4", OPTION_MASK_ISA2_SM4 }, - { "-mevex512", OPTION_MASK_ISA2_EVEX512 }, { "-musermsr", OPTION_MASK_ISA2_USER_MSR }, - { "-mavx10.1-256", OPTION_MASK_ISA2_AVX10_1_256 }, { "-mavx10.1", OPTION_MASK_ISA2_AVX10_1 }, { "-mavx10.2", OPTION_MASK_ISA2_AVX10_2 }, { "-mamx-avx512", OPTION_MASK_ISA2_AMX_AVX512 }, @@ -713,8 +711,6 @@ ix86_function_specific_save (struct cl_target_option *ptr, ptr->x_ix86_apx_features = opts->x_ix86_apx_features; ptr->x_ix86_isa_flags_explicit = opts->x_ix86_isa_flags_explicit; ptr->x_ix86_isa_flags2_explicit = opts->x_ix86_isa_flags2_explicit; - ptr->x_ix86_no_avx512_explicit = opts->x_ix86_no_avx512_explicit; - ptr->x_ix86_no_avx10_1_explicit = opts->x_ix86_no_avx10_1_explicit; ptr->x_recip_mask_explicit = opts->x_recip_mask_explicit; ptr->x_ix86_arch_string = opts->x_ix86_arch_string; ptr->x_ix86_tune_string = opts->x_ix86_tune_string; @@ -764,63 +760,63 @@ static unsigned HOST_WIDE_INT initial_ix86_arch_features[X86_ARCH_LAST] = { /* This table must be in sync with enum processor_type in i386.h. */ static const struct processor_costs *processor_cost_table[] = { - &generic_cost, - &i386_cost, - &i486_cost, - &pentium_cost, - &lakemont_cost, - &pentiumpro_cost, - &pentium4_cost, - &nocona_cost, - &core_cost, - &core_cost, - &core_cost, - &core_cost, - &atom_cost, - &slm_cost, - &slm_cost, - &slm_cost, - &tremont_cost, - &alderlake_cost, - &alderlake_cost, - &alderlake_cost, - &skylake_cost, - &skylake_cost, - &icelake_cost, - &icelake_cost, - &icelake_cost, - &skylake_cost, - &icelake_cost, - &skylake_cost, - &icelake_cost, - &alderlake_cost, - &icelake_cost, - &icelake_cost, - &icelake_cost, - &alderlake_cost, - &alderlake_cost, - &alderlake_cost, - &icelake_cost, - &intel_cost, - &lujiazui_cost, - &yongfeng_cost, - &shijidadao_cost, - &geode_cost, - &k6_cost, - &athlon_cost, - &k8_cost, - &amdfam10_cost, - &bdver_cost, - &bdver_cost, - &bdver_cost, - &bdver_cost, - &btver1_cost, - &btver2_cost, - &znver1_cost, - &znver2_cost, - &znver3_cost, - &znver4_cost, - &znver5_cost + &generic_cost, /* PROCESSOR_GENERIC. */ + &i386_cost, /* PROCESSOR_I386. */ + &i486_cost, /* PROCESSOR_I486. */ + &pentium_cost, /* PROCESSOR_PENTIUM. */ + &lakemont_cost, /* PROCESSOR_LAKEMONT. */ + &pentiumpro_cost, /* PROCESSOR_PENTIUMPRO. */ + &pentium4_cost, /* PROCESSOR_PENTIUM4. */ + &nocona_cost, /* PROCESSOR_NOCONA. */ + &core_cost, /* PROCESSOR_CORE2. */ + &core_cost, /* PROCESSOR_NEHALEM. */ + &core_cost, /* PROCESSOR_SANDYBRIDGE. */ + &core_cost, /* PROCESSOR_HASWELL. */ + &atom_cost, /* PROCESSOR_BONNELL. */ + &slm_cost, /* PROCESSOR_SILVERMONT. */ + &slm_cost, /* PROCESSOR_GOLDMONT. */ + &slm_cost, /* PROCESSOR_GOLDMONT_PLUS. */ + &tremont_cost, /* PROCESSOR_TREMONT. */ + &alderlake_cost, /* PROCESSOR_SIERRAFOREST. */ + &alderlake_cost, /* PROCESSOR_GRANDRIDGE. */ + &alderlake_cost, /* PROCESSOR_CLEARWATERFOREST. */ + &skylake_cost, /* PROCESSOR_SKYLAKE. */ + &skylake_cost, /* PROCESSOR_SKYLAKE_AVX512. */ + &icelake_cost, /* PROCESSOR_CANNONLAKE. */ + &icelake_cost, /* PROCESSOR_ICELAKE_CLIENT. */ + &icelake_cost, /* PROCESSOR_ICELAKE_SERVER. */ + &skylake_cost, /* PROCESSOR_CASCADELAKE. */ + &icelake_cost, /* PROCESSOR_TIGERLAKE. */ + &skylake_cost, /* PROCESSOR_COOPERLAKE. */ + &icelake_cost, /* PROCESSOR_SAPPHIRERAPIDS. */ + &alderlake_cost, /* PROCESSOR_ALDERLAKE. */ + &icelake_cost, /* PROCESSOR_ROCKETLAKE. */ + &icelake_cost, /* PROCESSOR_GRANITERAPIDS. */ + &icelake_cost, /* PROCESSOR_GRANITERAPIDS_D. */ + &alderlake_cost, /* PROCESSOR_ARROWLAKE. */ + &alderlake_cost, /* PROCESSOR_ARROWLAKE_S. */ + &alderlake_cost, /* PROCESSOR_PANTHERLAKE. */ + &icelake_cost, /* PROCESSOR_DIAMONDRAPIDS. */ + &alderlake_cost, /* PROCESSOR_INTEL. */ + &lujiazui_cost, /* PROCESSOR_LUJIAZUI. */ + &yongfeng_cost, /* PROCESSOR_YONGFENG. */ + &shijidadao_cost, /* PROCESSOR_SHIJIDADAO. */ + &geode_cost, /* PROCESSOR_GEODE. */ + &k6_cost, /* PROCESSOR_K6. */ + &athlon_cost, /* PROCESSOR_ATHLON. */ + &k8_cost, /* PROCESSOR_K8. */ + &amdfam10_cost, /* PROCESSOR_AMDFAM10. */ + &bdver_cost, /* PROCESSOR_BDVER1. */ + &bdver_cost, /* PROCESSOR_BDVER2. */ + &bdver_cost, /* PROCESSOR_BDVER3. */ + &bdver_cost, /* PROCESSOR_BDVER4. */ + &btver1_cost, /* PROCESSOR_BTVER1. */ + &btver2_cost, /* PROCESSOR_BTVER2. */ + &znver1_cost, /* PROCESSOR_ZNVER1. */ + &znver2_cost, /* PROCESSOR_ZNVER2. */ + &znver3_cost, /* PROCESSOR_ZNVER3. */ + &znver4_cost, /* PROCESSOR_ZNVER4. */ + &znver5_cost /* PROCESSOR_ZNVER5. */ }; /* Guarantee that the array is aligned with enum processor_type. */ @@ -858,8 +854,6 @@ ix86_function_specific_restore (struct gcc_options *opts, opts->x_ix86_apx_features = ptr->x_ix86_apx_features; opts->x_ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit; opts->x_ix86_isa_flags2_explicit = ptr->x_ix86_isa_flags2_explicit; - opts->x_ix86_no_avx512_explicit = ptr->x_ix86_no_avx512_explicit; - opts->x_ix86_no_avx10_1_explicit = ptr->x_ix86_no_avx10_1_explicit; opts->x_recip_mask_explicit = ptr->x_recip_mask_explicit; opts->x_ix86_arch_string = ptr->x_ix86_arch_string; opts->x_ix86_tune_string = ptr->x_ix86_tune_string; @@ -1131,11 +1125,8 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], IX86_ATTR_ISA ("sha512", OPT_msha512), IX86_ATTR_ISA ("sm4", OPT_msm4), IX86_ATTR_ISA ("apxf", OPT_mapxf), - IX86_ATTR_ISA ("evex512", OPT_mevex512), IX86_ATTR_ISA ("usermsr", OPT_musermsr), - IX86_ATTR_ISA ("avx10.1-256", OPT_mavx10_1_256), IX86_ATTR_ISA ("avx10.1", OPT_mavx10_1), - IX86_ATTR_ISA ("avx10.1-512", OPT_mavx10_1), IX86_ATTR_ISA ("avx10.2", OPT_mavx10_2), IX86_ATTR_ISA ("amx-avx512", OPT_mamx_avx512), IX86_ATTR_ISA ("amx-tf32", OPT_mamx_tf32), @@ -1429,18 +1420,6 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args, target_clone_attr)) return error_mark_node; - /* AVX10.1-256 will enable only 256 bit AVX512F features by setting all - AVX512 related ISA flags and not setting EVEX512. When it is used - with avx512 related function attribute, we need to enable 512 bit to - align with the command line behavior. Manually set EVEX512 for this - scenario. */ - if ((def->x_ix86_isa_flags2 & OPTION_MASK_ISA2_AVX10_1_256) - && (opts->x_ix86_isa_flags & OPTION_MASK_ISA_AVX512F) - && (opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512F) - && !(def->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512) - && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512)) - opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_EVEX512; - /* If the changed options are different from the default, rerun ix86_option_override_internal, and then save the options away. The string options are attribute options, and will be undone @@ -1451,10 +1430,7 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args, || option_strings[IX86_FUNCTION_SPECIFIC_ARCH] || option_strings[IX86_FUNCTION_SPECIFIC_TUNE] || enum_opts_set.x_ix86_fpmath - || enum_opts_set.x_prefer_vector_width_type - || (!(def->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_AVX10_1_256) - && (opts->x_ix86_isa_flags2_explicit - & OPTION_MASK_ISA2_AVX10_1_256))) + || enum_opts_set.x_prefer_vector_width_type) { /* If we are using the default tune= or arch=, undo the string assigned, and use the default. */ @@ -2018,7 +1994,7 @@ ix86_option_override_internal (bool main_args_p, struct gcc_options *opts_set) { unsigned int i; - unsigned HOST_WIDE_INT ix86_arch_mask, avx512_isa_flags, avx512_isa_flags2; + unsigned HOST_WIDE_INT ix86_arch_mask; const bool ix86_tune_specified = (opts->x_ix86_tune_string != NULL); /* -mrecip options. */ @@ -2037,15 +2013,6 @@ ix86_option_override_internal (bool main_args_p, { "vec-sqrt", RECIP_MASK_VEC_SQRT }, }; - avx512_isa_flags = OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX512CD - | OPTION_MASK_ISA_AVX512DQ | OPTION_MASK_ISA_AVX512BW - | OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA_AVX512IFMA - | OPTION_MASK_ISA_AVX512VBMI | OPTION_MASK_ISA_AVX512VBMI2 - | OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VPOPCNTDQ - | OPTION_MASK_ISA_AVX512BITALG; - avx512_isa_flags2 = OPTION_MASK_ISA2_AVX512FP16 - | OPTION_MASK_ISA2_AVX512BF16; - /* Turn off both OPTION_MASK_ABI_64 and OPTION_MASK_ABI_X32 if TARGET_64BIT_DEFAULT is true and TARGET_64BIT is false. */ if (TARGET_64BIT_DEFAULT && !TARGET_64BIT_P (opts->x_ix86_isa_flags)) @@ -2667,107 +2634,6 @@ ix86_option_override_internal (bool main_args_p, &= ~((OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_BMI2 | OPTION_MASK_ISA_TBM) & ~opts->x_ix86_isa_flags_explicit); - /* Emit a warning if AVX10.1 options is used with AVX512/EVEX512 options except - for the following option combinations: - 1. Both AVX10.1-512 and AVX512 with 512 bit vector width are enabled with no - explicit disable on other AVX512 features. - 2. Both AVX10.1-256 and AVX512 w/o 512 bit vector width are enabled with no - explicit disable on other AVX512 features. - 3. Both AVX10.1 and AVX512 are disabled. */ - if (TARGET_AVX10_1_P (opts->x_ix86_isa_flags2)) - { - if (opts->x_ix86_no_avx512_explicit - && (((~(avx512_isa_flags & opts->x_ix86_isa_flags) - & (avx512_isa_flags & opts->x_ix86_isa_flags_explicit))) - || ((~((avx512_isa_flags2 | OPTION_MASK_ISA2_EVEX512) - & opts->x_ix86_isa_flags2) - & ((avx512_isa_flags2 | OPTION_MASK_ISA2_EVEX512) - & opts->x_ix86_isa_flags2_explicit))))) - warning (0, "%<-mno-evex512%> or %<-mno-avx512XXX%> cannot disable " - "AVX10 instructions when AVX10.1-512 is available in GCC 15, " - "behavior will change to it will disable that part of " - "AVX512 instructions since GCC 16"); - } - else if (TARGET_AVX10_1_256_P (opts->x_ix86_isa_flags2)) - { - if (TARGET_EVEX512_P (opts->x_ix86_isa_flags2) - && (OPTION_MASK_ISA2_EVEX512 & opts->x_ix86_isa_flags2_explicit)) - { - if (!TARGET_AVX512F_P (opts->x_ix86_isa_flags) - || !(OPTION_MASK_ISA_AVX512F & opts->x_ix86_isa_flags_explicit)) - { - /* We should not emit 512 bit instructions under AVX10.1-256 - when EVEX512 is enabled w/o any AVX512 features enabled. - Disable EVEX512 bit for this. */ - warning (0, "Using %<-mevex512%> without any AVX512 features " - "enabled together with AVX10.1 only will not enable " - "any AVX512 or AVX10.1-512 features, using 256 as " - "max vector size"); - opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_EVEX512; - } - else - warning (0, "Vector size conflicts between AVX10.1 and AVX512, " - "using 512 as max vector size"); - } - else if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) - && (opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512F) - && !(OPTION_MASK_ISA2_EVEX512 - & opts->x_ix86_isa_flags2_explicit)) - warning (0, "Vector size conflicts between AVX10.1 and AVX512, using " - "512 as max vector size"); - else if (opts->x_ix86_no_avx512_explicit - && (((~(avx512_isa_flags & opts->x_ix86_isa_flags) - & (avx512_isa_flags & opts->x_ix86_isa_flags_explicit))) - || ((~(avx512_isa_flags2 & opts->x_ix86_isa_flags2) - & (avx512_isa_flags2 - & opts->x_ix86_isa_flags2_explicit))))) - warning (0, "%<-mno-avx512XXX%> cannot disable AVX10 instructions " - "when AVX10 is available in GCC 15, behavior will change " - "to it will disable that part of AVX512 instructions since " - "GCC 16"); - } - else if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) - && (OPTION_MASK_ISA_AVX512F & opts->x_ix86_isa_flags_explicit)) - { - if (opts->x_ix86_no_avx10_1_explicit - && ((OPTION_MASK_ISA2_AVX10_1_256 | OPTION_MASK_ISA2_AVX10_1) - & opts->x_ix86_isa_flags2_explicit)) - { - warning (0, "%<-mno-avx10.1-256, -mno-avx10.1-512%> cannot disable " - "AVX512 instructions when %<-mavx512XXX%> in GCC 15, " - "behavior will change to it will disable all the " - "instructions in GCC 16"); - /* Reset those unset AVX512 flags set by AVX10 options when AVX10 is - disabled. */ - if (OPTION_MASK_ISA2_AVX10_1_256 & opts->x_ix86_isa_flags2_explicit) - { - opts->x_ix86_isa_flags = (~avx512_isa_flags - & opts->x_ix86_isa_flags) - | (avx512_isa_flags & opts->x_ix86_isa_flags - & opts->x_ix86_isa_flags_explicit); - opts->x_ix86_isa_flags2 = (~avx512_isa_flags2 - & opts->x_ix86_isa_flags2) - | (avx512_isa_flags2 & opts->x_ix86_isa_flags2 - & opts->x_ix86_isa_flags2_explicit); - } - } - } - - /* Set EVEX512 if one of the following conditions meets: - 1. AVX512 is enabled while EVEX512 is not explicitly set/unset. - 2. AVX10.1-512 is enabled. */ - if (TARGET_AVX10_1_P (opts->x_ix86_isa_flags2) - || (TARGET_AVX512F_P (opts->x_ix86_isa_flags) - && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512))) - opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_EVEX512; - - /* Enable all AVX512 related ISAs when AVX10.1 is enabled. */ - if (TARGET_AVX10_1_256_P (opts->x_ix86_isa_flags2)) - { - opts->x_ix86_isa_flags |= avx512_isa_flags; - opts->x_ix86_isa_flags2 |= avx512_isa_flags2; - } - /* Validate -mpreferred-stack-boundary= value or default it to PREFERRED_STACK_BOUNDARY_DEFAULT. */ ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT; @@ -3042,8 +2908,7 @@ ix86_option_override_internal (bool main_args_p, opts->x_ix86_move_max = opts->x_prefer_vector_width_type; if (opts_set->x_ix86_move_max == PVW_NONE) { - if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) - && TARGET_EVEX512_P (opts->x_ix86_isa_flags2)) + if (TARGET_AVX512F_P (opts->x_ix86_isa_flags)) opts->x_ix86_move_max = PVW_AVX512; /* Align with vectorizer to avoid potential STLF issue. */ else if (TARGET_AVX_P (opts->x_ix86_isa_flags)) @@ -3069,8 +2934,7 @@ ix86_option_override_internal (bool main_args_p, opts->x_ix86_store_max = opts->x_prefer_vector_width_type; if (opts_set->x_ix86_store_max == PVW_NONE) { - if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) - && TARGET_EVEX512_P (opts->x_ix86_isa_flags2)) + if (TARGET_AVX512F_P (opts->x_ix86_isa_flags)) opts->x_ix86_store_max = PVW_AVX512; /* Align with vectorizer to avoid potential STLF issue. */ else if (TARGET_AVX_P (opts->x_ix86_isa_flags)) @@ -3367,13 +3231,13 @@ ix86_simd_clone_adjust (struct cgraph_node *node) case 'e': if (TARGET_PREFER_AVX256) { - if (!TARGET_AVX512F || !TARGET_EVEX512) - str = "avx512f,evex512,prefer-vector-width=512"; + if (!TARGET_AVX512F) + str = "avx512f,prefer-vector-width=512"; else str = "prefer-vector-width=512"; } - else if (!TARGET_AVX512F || !TARGET_EVEX512) - str = "avx512f,evex512"; + else if (!TARGET_AVX512F) + str = "avx512f"; break; default: gcc_unreachable (); @@ -3413,19 +3277,21 @@ ix86_set_func_type (tree fndecl) interrupt function in this case. */ enum call_saved_registers_type no_callee_saved_registers = TYPE_DEFAULT_CALL_SAVED_REGISTERS; - if (lookup_attribute ("no_callee_saved_registers", - TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + if (lookup_attribute ("preserve_none", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + no_callee_saved_registers = TYPE_PRESERVE_NONE; + else if ((lookup_attribute ("no_callee_saved_registers", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + || (ix86_noreturn_no_callee_saved_registers + && TREE_THIS_VOLATILE (fndecl) + && optimize + && !optimize_debug + && (TREE_NOTHROW (fndecl) || !flag_exceptions) + && !lookup_attribute ("interrupt", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl))) + && !lookup_attribute ("no_caller_saved_registers", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))) no_callee_saved_registers = TYPE_NO_CALLEE_SAVED_REGISTERS; - else if (ix86_noreturn_no_callee_saved_registers - && TREE_THIS_VOLATILE (fndecl) - && optimize - && !optimize_debug - && (TREE_NOTHROW (fndecl) || !flag_exceptions) - && !lookup_attribute ("interrupt", - TYPE_ATTRIBUTES (TREE_TYPE (fndecl))) - && !lookup_attribute ("no_caller_saved_registers", - TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) - no_callee_saved_registers = TYPE_NO_CALLEE_SAVED_REGISTERS_EXCEPT_BP; if (cfun->machine->func_type == TYPE_UNKNOWN) { @@ -3437,9 +3303,16 @@ ix86_set_func_type (tree fndecl) "interrupt and naked attributes are not compatible"); if (no_callee_saved_registers) - error_at (DECL_SOURCE_LOCATION (fndecl), - "%qs and %qs attributes are not compatible", - "interrupt", "no_callee_saved_registers"); + { + const char *attr; + if (no_callee_saved_registers == TYPE_PRESERVE_NONE) + attr = "preserve_none"; + else + attr = "no_callee_saved_registers"; + error_at (DECL_SOURCE_LOCATION (fndecl), + "%qs and %qs attributes are not compatible", + "interrupt", attr); + } int nargs = 0; for (tree arg = DECL_ARGUMENTS (fndecl); @@ -3461,21 +3334,13 @@ ix86_set_func_type (tree fndecl) else { cfun->machine->func_type = TYPE_NORMAL; - if (lookup_attribute ("no_caller_saved_registers", - TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + if (no_callee_saved_registers) + cfun->machine->call_saved_registers + = no_callee_saved_registers; + else if (lookup_attribute ("no_caller_saved_registers", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) cfun->machine->call_saved_registers = TYPE_NO_CALLER_SAVED_REGISTERS; - if (no_callee_saved_registers) - { - if (cfun->machine->call_saved_registers - == TYPE_NO_CALLER_SAVED_REGISTERS) - error_at (DECL_SOURCE_LOCATION (fndecl), - "%qs and %qs attributes are not compatible", - "no_caller_saved_registers", - "no_callee_saved_registers"); - cfun->machine->call_saved_registers - = no_callee_saved_registers; - } } } } @@ -3664,11 +3529,21 @@ ix86_set_current_function (tree fndecl) || (cfun->machine->call_saved_registers == TYPE_NO_CALLER_SAVED_REGISTERS)) { - /* Don't allow SSE, MMX nor x87 instructions since they - may change processor state. */ + /* Don't allow AVX, AVX512, MMX nor x87 instructions since they + may change processor state. Don't allow SSE instructions in + exception/interrupt service routines. */ const char *isa; if (TARGET_SSE) - isa = "SSE"; + { + if (TARGET_AVX512F) + isa = "AVX512"; + else if (TARGET_AVX) + isa = "AVX"; + else if (cfun->machine->func_type != TYPE_NORMAL) + isa = "SSE"; + else + isa = NULL; + } else if (TARGET_MMX) isa = "MMX/3Dnow"; else if (TARGET_80387) @@ -4093,9 +3968,50 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int, } static tree -ix86_handle_call_saved_registers_attribute (tree *, tree, tree, +ix86_handle_call_saved_registers_attribute (tree *node, tree name, tree, int, bool *) { + const char *attr1 = nullptr; + const char *attr2 = nullptr; + + if (is_attribute_p ("no_callee_saved_registers", name)) + { + /* Disallow preserve_none and no_caller_saved_registers + attributes. */ + attr1 = "no_callee_saved_registers"; + if (lookup_attribute ("preserve_none", TYPE_ATTRIBUTES (*node))) + attr2 = "preserve_none"; + else if (lookup_attribute ("no_caller_saved_registers", + TYPE_ATTRIBUTES (*node))) + attr2 = "no_caller_saved_registers"; + } + else if (is_attribute_p ("no_caller_saved_registers", name)) + { + /* Disallow preserve_none and no_callee_saved_registers + attributes. */ + attr1 = "no_caller_saved_registers"; + if (lookup_attribute ("preserve_none", TYPE_ATTRIBUTES (*node))) + attr2 = "preserve_none"; + else if (lookup_attribute ("no_callee_saved_registers", + TYPE_ATTRIBUTES (*node))) + attr2 = "no_callee_saved_registers"; + } + else if (is_attribute_p ("preserve_none", name)) + { + /* Disallow no_callee_saved_registers and no_caller_saved_registers + attributes. */ + attr1 = "preserve_none"; + if (lookup_attribute ("no_callee_saved_registers", + TYPE_ATTRIBUTES (*node))) + attr2 = "no_caller_saved_registers"; + else if (lookup_attribute ("no_callee_saved_registers", + TYPE_ATTRIBUTES (*node))) + attr2 = "no_callee_saved_registers"; + } + + if (attr2) + error ("%qs and %qs attributes are not compatible", attr1, attr2); + return NULL_TREE; } @@ -4257,6 +4173,8 @@ static const attribute_spec ix86_gnu_attributes[] = ix86_handle_interrupt_attribute, NULL }, { "no_caller_saved_registers", 0, 0, false, true, true, false, ix86_handle_call_saved_registers_attribute, NULL }, + { "preserve_none", 0, 0, false, true, true, true, + ix86_handle_call_saved_registers_attribute, NULL }, { "no_callee_saved_registers", 0, 0, false, true, true, true, ix86_handle_call_saved_registers_attribute, NULL }, { "naked", 0, 0, true, false, false, false, |