Hello! I have committed following patch that also implements ix86_target_string handling of the new option.
2016-05-25 Uros Bizjak <ubiz...@gmail.com> H.J. Lu <hongjiu...@intel.com> PR target/70738 * common/config/i386/i386-common.c (OPTION_MASK_ISA_GENERAL_REGS_ONLY_UNSET): New. (ix86_handle_option) <case OPT_mgeneral_regs_only>: Disable MPX, MMX, SSE and x87 instructions for -mgeneral-regs-only. * config/i386/i386.opt (ix86_target_flags): Add new Variable. (-mgeneral-regs-only): Add new option. * config/i386/i386.c (ix86_option_override_internal): Don't enable x87 instructions if only general registers are allowed. (ix86_target_string): Add ix86_flags argument. Handle additional flags options through ix86_flags argument. Update all callers. * doc/invoke.texi: Document -mgeneral-regs-only. testsuite/ChangeLog: 2016-05-25 H.J. Lu <hongjiu...@intel.com> PR target/70738 * gcc.target/i386/pr70738-1.c: New test. * gcc.target/i386/pr70738-2.c: Likewise. * gcc.target/i386/pr70738-3.c: Likewise. * gcc.target/i386/pr70738-4.c: Likewise. * gcc.target/i386/pr70738-5.c: Likewise. * gcc.target/i386/pr70738-6.c: Likewise. * gcc.target/i386/pr70738-7.c: Likewise. * gcc.target/i386/pr70738-8.c: Likewise. * gcc.target/i386/pr70738-9.c: Likewise. Added is also a removal of a couple of unneeded variables: 2016-05-25 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.opt (ix86_target_flags_explicit): Remove. (x_ix86_target_flags_explicit): Remove. * config/i386/i386.c (ix86_function_specific_save): Do not copy x_ix86_target_flags_explicit. (ix86_function_specific_restore): Ditto. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: common/config/i386/i386-common.c =================================================================== --- common/config/i386/i386-common.c (revision 236737) +++ common/config/i386/i386-common.c (working copy) @@ -223,6 +223,11 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA_RDRND_UNSET OPTION_MASK_ISA_RDRND #define OPTION_MASK_ISA_F16C_UNSET OPTION_MASK_ISA_F16C +#define OPTION_MASK_ISA_GENERAL_REGS_ONLY_UNSET \ + (OPTION_MASK_ISA_MMX_UNSET \ + | OPTION_MASK_ISA_SSE_UNSET \ + | OPTION_MASK_ISA_MPX) + /* Implement TARGET_HANDLE_OPTION. */ bool @@ -236,6 +241,22 @@ ix86_handle_option (struct gcc_options *opts, switch (code) { + case OPT_mgeneral_regs_only: + if (value) + { + /* Disable MPX, MMX, SSE and x87 instructions if only + general registers are allowed. */ + opts->x_ix86_isa_flags + &= ~OPTION_MASK_ISA_GENERAL_REGS_ONLY_UNSET; + opts->x_ix86_isa_flags_explicit + |= OPTION_MASK_ISA_GENERAL_REGS_ONLY_UNSET; + + opts->x_target_flags &= ~MASK_80387; + } + else + gcc_unreachable (); + return true; + case OPT_mmmx: if (value) { Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 236737) +++ config/i386/i386.c (working copy) @@ -2586,7 +2586,7 @@ enum ix86_function_specific_strings IX86_FUNCTION_SPECIFIC_MAX }; -static char *ix86_target_string (HOST_WIDE_INT, int, const char *, +static char *ix86_target_string (HOST_WIDE_INT, int, int, const char *, const char *, enum fpmath_unit, bool); static void ix86_function_specific_save (struct cl_target_option *, struct gcc_options *opts); @@ -4084,9 +4084,9 @@ ix86_using_red_zone (void) responsible for freeing the string. */ static char * -ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, - const char *tune, enum fpmath_unit fpmath, - bool add_nl_p) +ix86_target_string (HOST_WIDE_INT isa, int flags, int ix86_flags, + const char *arch, const char *tune, + enum fpmath_unit fpmath, bool add_nl_p) { struct ix86_target_opts { @@ -4189,10 +4189,18 @@ static char * { "-mprefer-avx128", MASK_PREFER_AVX128}, }; - const char *opts[ARRAY_SIZE (isa_opts) + ARRAY_SIZE (flag_opts) + 6][2]; + /* Additional flag options. */ + static struct ix86_target_opts ix86_flag_opts[] = + { + { "-mgeneral-regs-only", OPTION_MASK_GENERAL_REGS_ONLY }, + }; + const char *opts[ARRAY_SIZE (isa_opts) + ARRAY_SIZE (flag_opts) + + ARRAY_SIZE (ix86_flag_opts) + 6][2]; + char isa_other[40]; char target_other[40]; + char ix86_target_other[40]; unsigned num = 0; unsigned i, j; char *ret; @@ -4266,6 +4274,22 @@ static char * sprintf (target_other, "(other flags: %#x)", flags); } + /* Add additional flag options. */ + for (i = 0; i < ARRAY_SIZE (ix86_flag_opts); i++) + { + if ((ix86_flags & ix86_flag_opts[i].mask) != 0) + { + opts[num++][0] = ix86_flag_opts[i].option; + ix86_flags &= ~ ix86_flag_opts[i].mask; + } + } + + if (ix86_flags && add_nl_p) + { + opts[num++][0] = ix86_target_other; + sprintf (ix86_target_other, "(other flags: %#x)", ix86_flags); + } + /* Add -fpmath= option. */ if (fpmath) { @@ -4360,6 +4384,7 @@ void ATTRIBUTE_UNUSED ix86_debug_options (void) { char *opts = ix86_target_string (ix86_isa_flags, target_flags, + ix86_target_flags, ix86_arch_string, ix86_tune_string, ix86_fpmath, true); @@ -5337,7 +5362,10 @@ ix86_option_override_internal (bool main_args_p, && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PKU)) opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PKU; - if (!(opts_set->x_target_flags & MASK_80387)) + /* Don't enable x87 instructions if only + general registers are allowed. */ + if (!(opts_set->x_ix86_target_flags & OPTION_MASK_GENERAL_REGS_ONLY) + && !(opts_set->x_target_flags & MASK_80387)) { if (processor_alias_table[i].flags & PTA_NO_80387) opts->x_target_flags &= ~MASK_80387; @@ -6075,7 +6103,6 @@ ix86_function_specific_save (struct cl_target_opti ptr->tune_defaulted = ix86_tune_defaulted; ptr->arch_specified = ix86_arch_specified; ptr->x_ix86_isa_flags_explicit = opts->x_ix86_isa_flags_explicit; - ptr->x_ix86_target_flags_explicit = opts->x_ix86_target_flags_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; @@ -6132,7 +6159,6 @@ ix86_function_specific_restore (struct gcc_options ix86_tune_defaulted = ptr->tune_defaulted; ix86_arch_specified = ptr->arch_specified; opts->x_ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit; - opts->x_ix86_target_flags_explicit = ptr->x_ix86_target_flags_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; @@ -6239,7 +6265,8 @@ ix86_function_specific_print (FILE *file, int inde { char *target_string = ix86_target_string (ptr->x_ix86_isa_flags, ptr->x_target_flags, - NULL, NULL, ptr->x_ix86_fpmath, false); + ptr->x_ix86_target_flags, NULL, NULL, + ptr->x_ix86_fpmath, false); gcc_assert (ptr->arch < PROCESSOR_max); fprintf (file, "%*sarch = %d (%s)\n", @@ -40593,9 +40620,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub if (ix86_builtins_isa[fcode].isa && !(ix86_builtins_isa[fcode].isa & ix86_isa_flags)) { - char *opts = ix86_target_string (ix86_builtins_isa[fcode].isa, 0, NULL, - NULL, (enum fpmath_unit) 0, false); - + char *opts = ix86_target_string (ix86_builtins_isa[fcode].isa, 0, 0, + NULL, NULL, (enum fpmath_unit) 0, + false); if (!opts) error ("%qE needs unknown isa option", fndecl); else Index: config/i386/i386.opt =================================================================== --- config/i386/i386.opt (revision 236737) +++ config/i386/i386.opt (working copy) @@ -30,6 +30,10 @@ HOST_WIDE_INT ix86_isa_flags = TARGET_64BIT_DEFAUL Variable HOST_WIDE_INT ix86_isa_flags_explicit +; Additional target flags +Variable +int ix86_target_flags + TargetVariable int recip_mask = RECIP_MASK_DEFAULT @@ -72,14 +76,6 @@ unsigned char branch_cost TargetSave HOST_WIDE_INT x_ix86_isa_flags_explicit -;; which flags were passed by the user -Variable -int ix86_target_flags_explicit - -;; which flags were passed by the user -TargetSave -HOST_WIDE_INT x_ix86_target_flags_explicit - ;; whether -mtune was not specified TargetSave unsigned char tune_defaulted @@ -897,3 +893,7 @@ Enum(stack_protector_guard) String(global) Value(S mmitigate-rop Target Var(flag_mitigate_rop) Init(0) Attempt to avoid generating instruction sequences containing ret bytes. + +mgeneral-regs-only +Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save +Generate code which uses only the general registers. Index: doc/invoke.texi =================================================================== --- doc/invoke.texi (revision 236737) +++ doc/invoke.texi (working copy) @@ -1173,7 +1173,7 @@ See RS/6000 and PowerPC Options. -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol --mmitigate-rop} +-mmitigate-rop -mgeneral-regs-only} @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -24298,6 +24298,12 @@ opcodes, to mitigate against certain forms of atta this option is limited in what it can do and should not be relied on to provide serious protection. +@item -mgeneral-regs-only +@opindex mgeneral-regs-only +Generate code that uses only the general-purpose registers. This +prevents the compiler from using floating-point, vector, mask and bound +registers. + @end table These @samp{-m} switches are supported in addition to the above Index: testsuite/gcc.target/i386/pr70738-1.c =================================================================== --- testsuite/gcc.target/i386/pr70738-1.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-1.c (working copy) @@ -0,0 +1,9 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2 -mgeneral-regs-only" } */ + +typedef int int32x2_t __attribute__ ((__vector_size__ ((8)))); + +int32x2_t test (int32x2_t a, int32x2_t b) +{ /* { dg-error "SSE register return with SSE disabled" } */ + return a + b; +} Index: testsuite/gcc.target/i386/pr70738-2.c =================================================================== --- testsuite/gcc.target/i386/pr70738-2.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-2.c (working copy) @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-mmmx -mgeneral-regs-only" } */ + +typedef int int32x2_t __attribute__ ((__vector_size__ ((8)))); + +int32x2_t +test (int32x2_t a, int32x2_t b) /* { dg-warning "MMX vector argument without MMX enabled" } */ +{ /* { dg-warning "MMX vector return without MMX enabled" } */ + return a + b; +} Index: testsuite/gcc.target/i386/pr70738-3.c =================================================================== --- testsuite/gcc.target/i386/pr70738-3.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-3.c (working copy) @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -mgeneral-regs-only" } */ + +typedef int int32x4_t __attribute__ ((__vector_size__ ((16)))); +extern int32x4_t c; + +void +test (int32x4_t a, int32x4_t b) /* { dg-warning "SSE vector argument without SSE enabled" } */ +{ + c = a + b; +} Index: testsuite/gcc.target/i386/pr70738-4.c =================================================================== --- testsuite/gcc.target/i386/pr70738-4.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-4.c (working copy) @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-msse2 -mgeneral-regs-only" } */ + +typedef int int32x4_t __attribute__ ((__vector_size__ ((16)))); + +int32x4_t +test (int32x4_t a, int32x4_t b) /* { dg-warning "SSE vector argument without SSE enabled" } */ +{ /* { dg-warning "SSE vector return without SSE enabled" } */ + return a + b; +} Index: testsuite/gcc.target/i386/pr70738-5.c =================================================================== --- testsuite/gcc.target/i386/pr70738-5.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-5.c (working copy) @@ -0,0 +1,16 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2 -mgeneral-regs-only" } */ + +#include <stdarg.h> + +typedef int int32x2_t __attribute__ ((__vector_size__ ((8)))); + +int +test (int i, ...) +{ + va_list argp; + va_start (argp, i); + int32x2_t x = (int32x2_t) {0, 1}; + x += va_arg (argp, int32x2_t); /* { dg-error "SSE register argument with SSE disabled" } */ + return x[0] + x[1]; +} Index: testsuite/gcc.target/i386/pr70738-6.c =================================================================== --- testsuite/gcc.target/i386/pr70738-6.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-6.c (working copy) @@ -0,0 +1,10 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2 -mgeneral-regs-only" } */ + +extern float a, b, c; + +void +foo (void) +{ + c = a * b; /* { dg-error "SSE register return with SSE disabled" } */ +} Index: testsuite/gcc.target/i386/pr70738-7.c =================================================================== --- testsuite/gcc.target/i386/pr70738-7.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-7.c (working copy) @@ -0,0 +1,13 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-msse2 -mgeneral-regs-only" } */ + +extern float a, b, c; + +void +foo (void) +{ + c = a * b; +} + +/* { dg-final { scan-assembler-not "mulss" } } */ +/* { dg-final { scan-assembler "call\[ \t\]__mulsf3" } } */ Index: testsuite/gcc.target/i386/pr70738-8.c =================================================================== --- testsuite/gcc.target/i386/pr70738-8.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-8.c (working copy) @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mgeneral-regs-only" } */ + +extern void abort (); + +int +dec (int a, int b) +{ + return a + b; +} + +int +cal (int a, int b) +{ + int sum1 = a * b; + int sum2 = a / b; + int sum = dec (sum1, sum2); + return a + b + sum + sum1 + sum2; +} + +int +main (int argc, char **argv) +{ + int ret = cal (2, 1); + + if (ret != 11) + abort (); + + return 0; +} Index: testsuite/gcc.target/i386/pr70738-9.c =================================================================== --- testsuite/gcc.target/i386/pr70738-9.c (nonexistent) +++ testsuite/gcc.target/i386/pr70738-9.c (working copy) @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mgeneral-regs-only" } */ + +extern void abort (); + +int +cal (int a, int b) +{ + int sum = a + b; + int sum1 = a * b; + return (a + b + sum + sum1); +} + +int +main (int argc, char **argv) +{ + int ret = cal (1, 2); + + if (ret != 8) + abort (); + + return 0; +}