#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
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
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])
&& !(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))
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.
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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];
+}
--- /dev/null
+/* { 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" } */
+}
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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
--- /dev/null
+/* { 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;
+}