From: H.J. Lu Date: Fri, 21 Aug 2020 16:42:49 +0000 (-0700) Subject: x86: Add target("general-regs-only") function attribute X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=87c753ac241f25d222d46ba1ac66ceba89d6a200;p=gcc.git x86: Add target("general-regs-only") function attribute gcc/ PR target/96744 * config/i386/i386-options.c (IX86_ATTR_IX86_YES): New. (IX86_ATTR_IX86_NO): Likewise. (ix86_opt_type): Add ix86_opt_ix86_yes and ix86_opt_ix86_no. (ix86_valid_target_attribute_inner_p): Handle general-regs-only, ix86_opt_ix86_yes and ix86_opt_ix86_no. (ix86_option_override_internal): Check opts->x_ix86_target_flags instead of opts->x_ix86_target_flags. * doc/extend.texi: Document target("general-regs-only") function attribute. gcc/testsuite/ PR target/96744 * gcc.target/i386/pr96744-1.c: New test. * gcc.target/i386/pr96744-2.c: Likewise. * gcc.target/i386/pr96744-3a.c: Likewise. * gcc.target/i386/pr96744-3b.c: Likewise. * gcc.target/i386/pr96744-4.c: Likewise. * gcc.target/i386/pr96744-5.c: Likewise. * gcc.target/i386/pr96744-6.c: Likewise. * gcc.target/i386/pr96744-7.c: Likewise. * gcc.target/i386/pr96744-8a.c: Likewise. * gcc.target/i386/pr96744-8b.c: Likewise. * gcc.target/i386/pr96744-9.c: Likewise. --- diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c index 26d1ea18ef1..e0fc68c27bf 100644 --- a/gcc/config/i386/i386-options.c +++ b/gcc/config/i386/i386-options.c @@ -922,12 +922,18 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], #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 } +#define IX86_ATTR_IX86_YES(S,O,M) \ + { S, sizeof (S)-1, ix86_opt_ix86_yes, O, M } +#define IX86_ATTR_IX86_NO(S,O,M) \ + { S, sizeof (S)-1, ix86_opt_ix86_no, O, M } enum ix86_opt_type { ix86_opt_unknown, ix86_opt_yes, ix86_opt_no, + ix86_opt_ix86_yes, + ix86_opt_ix86_no, ix86_opt_str, ix86_opt_enum, ix86_opt_isa @@ -1062,6 +1068,10 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], IX86_ATTR_YES ("recip", OPT_mrecip, MASK_RECIP), + + IX86_ATTR_IX86_YES ("general-regs-only", + OPT_mgeneral_regs_only, + OPTION_MASK_GENERAL_REGS_ONLY), }; location_t loc @@ -1175,6 +1185,33 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], opts->x_target_flags &= ~mask; } + else if (type == ix86_opt_ix86_yes || type == ix86_opt_ix86_no) + { + if (mask == OPTION_MASK_GENERAL_REGS_ONLY) + { + if (type != ix86_opt_ix86_yes) + gcc_unreachable (); + + opts->x_ix86_target_flags |= mask; + + struct cl_decoded_option decoded; + generate_option (opt, NULL, opt_set_p, CL_TARGET, + &decoded); + ix86_handle_option (opts, opts_set, &decoded, + input_location); + } + else + { + if (type == ix86_opt_ix86_no) + opt_set_p = !opt_set_p; + + if (opt_set_p) + opts->x_ix86_target_flags |= mask; + else + opts->x_ix86_target_flags &= ~mask; + } + } + else if (type == ix86_opt_str) { if (p_strings[opt]) @@ -2260,9 +2297,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; - /* Don't enable x87 instructions if only - general registers are allowed. */ - if (!(opts_set->x_ix86_target_flags & OPTION_MASK_GENERAL_REGS_ONLY) + /* Don't enable x87 instructions if only general registers are + allowed by target("general-regs-only") function attribute or + -mgeneral-regs-only. */ + if (!(opts->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) != 0)) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index fd794961e0a..2bb9b2f72f5 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -6656,6 +6656,10 @@ Enable/disable the generation of RCPSS, RCPPS, RSQRTSS and RSQRTPS instructions followed an additional Newton-Raphson step instead of doing a floating-point division. +@item general-regs-only +@cindex @code{target("general-regs-only")} function attribute, x86 +Generate code which uses only the general registers. + @item arch=@var{ARCH} @cindex @code{target("arch=@var{ARCH}")} function attribute, x86 Specify the architecture to generate code for in compiling the function. diff --git a/gcc/testsuite/gcc.target/i386/pr96744-1.c b/gcc/testsuite/gcc.target/i386/pr96744-1.c new file mode 100644 index 00000000000..46f3ce6ddd4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2" } */ + +typedef int int32x2_t __attribute__ ((__vector_size__ ((8)))); + +__attribute__((__target__("general-regs-only"))) +int32x2_t test (int32x2_t a, int32x2_t b) +{ /* { dg-error "SSE register return with SSE disabled" } */ + return a + b; +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-2.c b/gcc/testsuite/gcc.target/i386/pr96744-2.c new file mode 100644 index 00000000000..4a436d8ef04 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-mmmx" } */ + +typedef int int32x2_t __attribute__ ((__vector_size__ ((8)))); + +__attribute__((__target__("general-regs-only"))) +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; +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-3a.c b/gcc/testsuite/gcc.target/i386/pr96744-3a.c new file mode 100644 index 00000000000..79191544eb4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-3a.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2" } */ + +typedef int int32x4_t __attribute__ ((__vector_size__ ((16)))); +extern int32x4_t c; + +__attribute__((__target__("general-regs-only"))) +void +test (int32x4_t a, int32x4_t b) /* { dg-warning "SSE vector argument without SSE enabled" } */ +{ + c = a + b; +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-3b.c b/gcc/testsuite/gcc.target/i386/pr96744-3b.c new file mode 100644 index 00000000000..389b5cf9897 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-3b.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2" } */ + +typedef int int32x4_t __attribute__ ((__vector_size__ ((16)))); +extern int32x4_t c; + +#pragma GCC push_options +#pragma GCC target("general-regs-only") + +void +test (int32x4_t a, int32x4_t b) /* { dg-warning "SSE vector argument without SSE enabled" } */ +{ + c = a + b; +} + +#pragma GCC pop_options diff --git a/gcc/testsuite/gcc.target/i386/pr96744-4.c b/gcc/testsuite/gcc.target/i386/pr96744-4.c new file mode 100644 index 00000000000..005329f95e9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-msse2" } */ + +typedef int int32x4_t __attribute__ ((__vector_size__ ((16)))); + +__attribute__((__target__("general-regs-only"))) +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; +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-5.c b/gcc/testsuite/gcc.target/i386/pr96744-5.c new file mode 100644 index 00000000000..18f2132aa27 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-5.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2" } */ + +#include + +typedef int int32x2_t __attribute__ ((__vector_size__ ((8)))); + +__attribute__((__target__("general-regs-only"))) +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]; +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-6.c b/gcc/testsuite/gcc.target/i386/pr96744-6.c new file mode 100644 index 00000000000..38a3cc7fa92 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-6.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2 -mfpmath=sse" } */ + +extern float a, b, c; + +__attribute__((__target__("general-regs-only"))) +void +foo (void) +{ + c = a * b; /* { dg-error "SSE register return with SSE disabled" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-7.c b/gcc/testsuite/gcc.target/i386/pr96744-7.c new file mode 100644 index 00000000000..5f55b6cbd33 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-7.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { ia32 && { ! *-*-darwin* } } } } */ +/* { dg-options "-msse2" } */ + +extern float a, b, c; + +__attribute__((__target__("general-regs-only"))) +void +foo (void) +{ + c = a * b; +} + +/* { dg-final { scan-assembler-not "mulss" } } */ +/* { dg-final { scan-assembler "call\[ \t\]__mulsf3" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr96744-8a.c b/gcc/testsuite/gcc.target/i386/pr96744-8a.c new file mode 100644 index 00000000000..d264e1e01d4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-8a.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (); + +__attribute__((__target__("general-regs-only"))) +int +dec (int a, int b) +{ + return a + b; +} + +__attribute__((__target__("general-regs-only"))) +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; +} + +__attribute__((__target__("general-regs-only"))) +int +main (int argc, char **argv) +{ + int ret = cal (2, 1); + + if (ret != 11) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr96744-8b.c b/gcc/testsuite/gcc.target/i386/pr96744-8b.c new file mode 100644 index 00000000000..30e763d932e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-8b.c @@ -0,0 +1,35 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#pragma GCC push_options +#pragma GCC target("general-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; +} + +#pragma GCC pop_options diff --git a/gcc/testsuite/gcc.target/i386/pr96744-9.c b/gcc/testsuite/gcc.target/i386/pr96744-9.c new file mode 100644 index 00000000000..196e86f08e9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr96744-9.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (); + +__attribute__((__target__("general-regs-only"))) +int +cal (int a, int b) +{ + int sum = a + b; + int sum1 = a * b; + return (a + b + sum + sum1); +} + +__attribute__((__target__("general-regs-only"))) +int +main (int argc, char **argv) +{ + int ret = cal (1, 2); + + if (ret != 8) + abort (); + + return 0; +}