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.
This commit is contained in:
H.J. Lu 2020-08-21 09:42:49 -07:00
parent dbc724d6d2
commit 87c753ac24
13 changed files with 240 additions and 3 deletions

View File

@ -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))

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -0,0 +1,17 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-options "-msse2" } */
#include <stdarg.h>
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];
}

View File

@ -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" } */
}

View File

@ -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" } } */

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}