Add ability to set target options (ix86 only) and optimization options on a function specific basis
From-SVN: r138075
This commit is contained in:
parent
5295185c31
commit
ab442df7fb
55 changed files with 4784 additions and 619 deletions
|
@ -794,7 +794,7 @@ BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def
|
|||
TREE_H = tree.h all-tree.def tree.def c-common.def $(lang_tree_files) \
|
||||
$(MACHMODE_H) tree-check.h $(BUILTINS_DEF) \
|
||||
$(INPUT_H) statistics.h vec.h treestruct.def $(HASHTAB_H) \
|
||||
double-int.h alias.h $(SYMTAB_H)
|
||||
double-int.h alias.h $(SYMTAB_H) options.h
|
||||
BASIC_BLOCK_H = basic-block.h $(BITMAP_H) sbitmap.h varray.h $(PARTITION_H) \
|
||||
hard-reg-set.h $(PREDICT_H) vec.h $(FUNCTION_H) \
|
||||
cfghooks.h $(OBSTACK_H)
|
||||
|
@ -1965,7 +1965,8 @@ s-options-h: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opth-gen.awk
|
|||
$(SHELL) $(srcdir)/../move-if-change tmp-options.h options.h
|
||||
$(STAMP) $@
|
||||
|
||||
options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
|
||||
options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(FLAGS_H) \
|
||||
$(TM_H) opts.h intl.h
|
||||
|
||||
gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) -DGCC_DRIVER options.c
|
||||
|
|
|
@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "target.h"
|
||||
#include "langhooks.h"
|
||||
#include "hashtab.h"
|
||||
#include "c-common.h"
|
||||
|
||||
static void init_attributes (void);
|
||||
|
||||
|
@ -232,6 +233,41 @@ decl_attributes (tree *node, tree attributes, int flags)
|
|||
if (!attributes_initialized)
|
||||
init_attributes ();
|
||||
|
||||
/* If this is a function and the user used #pragma GCC optimize, add the
|
||||
options to the attribute((optimize(...))) list. */
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
|
||||
{
|
||||
tree cur_attr = lookup_attribute ("optimize", attributes);
|
||||
tree opts = copy_list (current_optimize_pragma);
|
||||
|
||||
if (! cur_attr)
|
||||
attributes
|
||||
= tree_cons (get_identifier ("optimize"), opts, attributes);
|
||||
else
|
||||
TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
|
||||
}
|
||||
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL
|
||||
&& optimization_current_node != optimization_default_node
|
||||
&& !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
|
||||
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
|
||||
|
||||
/* If this is a function and the user used #pragma GCC option, add the
|
||||
options to the attribute((option(...))) list. */
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL
|
||||
&& current_option_pragma
|
||||
&& targetm.target_option.valid_attribute_p (*node, NULL_TREE,
|
||||
current_option_pragma, 0))
|
||||
{
|
||||
tree cur_attr = lookup_attribute ("option", attributes);
|
||||
tree opts = copy_list (current_option_pragma);
|
||||
|
||||
if (! cur_attr)
|
||||
attributes = tree_cons (get_identifier ("option"), opts, attributes);
|
||||
else
|
||||
TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
|
||||
}
|
||||
|
||||
targetm.insert_attributes (*node, &attributes);
|
||||
|
||||
for (a = attributes; a; a = TREE_CHAIN (a))
|
||||
|
|
245
gcc/c-common.c
245
gcc/c-common.c
|
@ -574,6 +574,8 @@ static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
|
|||
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_option_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
|
||||
|
||||
static void check_function_nonnull (tree, int, tree *);
|
||||
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
|
||||
|
@ -857,6 +859,10 @@ const struct attribute_spec c_common_attribute_table[] =
|
|||
handle_error_attribute },
|
||||
{ "error", 1, 1, true, false, false,
|
||||
handle_error_attribute },
|
||||
{ "option", 1, -1, true, false, false,
|
||||
handle_option_attribute },
|
||||
{ "optimize", 1, -1, true, false, false,
|
||||
handle_optimize_attribute },
|
||||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
||||
|
@ -5027,7 +5033,7 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
|||
|
||||
static tree
|
||||
handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
{
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||
{
|
||||
|
@ -5037,8 +5043,34 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
|||
name, "cold");
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
/* Do nothing else, just set the attribute. We'll get at
|
||||
it later with lookup_attribute. */
|
||||
|
||||
else
|
||||
{
|
||||
tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
|
||||
|
||||
/* If we are not at -O3, but are optimizing, turn on -O3
|
||||
optimizations just for this one function. */
|
||||
if (((optimize > 0 && optimize < 3) || optimize_size)
|
||||
&& (!old_opts || old_opts == optimization_default_node))
|
||||
{
|
||||
/* Create the hot optimization node if needed. */
|
||||
if (!optimization_hot_node)
|
||||
{
|
||||
struct cl_optimization current_options;
|
||||
static const char *os_argv[] = { NULL, "-O3", NULL };
|
||||
|
||||
cl_optimization_save (¤t_options);
|
||||
decode_options (2, os_argv);
|
||||
optimization_hot_node = build_optimization_node ();
|
||||
cl_optimization_restore (¤t_options);
|
||||
}
|
||||
|
||||
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
|
||||
= optimization_hot_node;
|
||||
}
|
||||
}
|
||||
/* Most of the rest of the hot processing is done later with
|
||||
lookup_attribute. */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5063,8 +5095,31 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
|||
name, "hot");
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
/* Do nothing else, just set the attribute. We'll get at
|
||||
it later with lookup_attribute. */
|
||||
else
|
||||
{
|
||||
tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
|
||||
|
||||
/* If we are optimizing, but not optimizing for space, turn on -Os
|
||||
optimizations just for this one function. */
|
||||
if (optimize && !optimize_size
|
||||
&& (!old_opts || old_opts == optimization_default_node))
|
||||
{
|
||||
/* Create the cold optimization node if needed. */
|
||||
if (!optimization_cold_node)
|
||||
{
|
||||
struct cl_optimization current_options;
|
||||
static const char *os_argv[] = { NULL, "-Os", NULL };
|
||||
|
||||
cl_optimization_save (¤t_options);
|
||||
decode_options (2, os_argv);
|
||||
optimization_cold_node = build_optimization_node ();
|
||||
cl_optimization_restore (¤t_options);
|
||||
}
|
||||
|
||||
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
|
||||
= optimization_cold_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6762,6 +6817,186 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
|
|||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* For handling "option" attribute. arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_option_attribute (tree *node, tree name, tree args, int flags,
|
||||
bool *no_add_attrs)
|
||||
{
|
||||
/* Ensure we have a function type. */
|
||||
if (TREE_CODE (*node) != FUNCTION_DECL)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
else if (targetm.target_option.valid_attribute_p
|
||||
== default_target_option_valid_attribute_p)
|
||||
{
|
||||
warning (OPT_Wattributes,
|
||||
"%qE attribute is not supported on this machine",
|
||||
name);
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
else if (! targetm.target_option.valid_attribute_p (*node, name, args,
|
||||
flags))
|
||||
*no_add_attrs = true;
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Arguments being collected for optimization. */
|
||||
typedef const char *const_char_p; /* For DEF_VEC_P. */
|
||||
DEF_VEC_P(const_char_p);
|
||||
DEF_VEC_ALLOC_P(const_char_p, gc);
|
||||
static GTY(()) VEC(const_char_p, gc) *optimize_args;
|
||||
|
||||
|
||||
/* Inner function to convert a TREE_LIST to argv string to parse the optimize
|
||||
options in ARGS. ATTR_P is true if this is for attribute(optimize), and
|
||||
false for #pragma GCC optimize. */
|
||||
|
||||
bool
|
||||
parse_optimize_options (tree args, bool attr_p)
|
||||
{
|
||||
bool ret = true;
|
||||
unsigned opt_argc;
|
||||
unsigned i;
|
||||
const char **opt_argv;
|
||||
tree ap;
|
||||
|
||||
/* Build up argv vector. Just in case the string is stored away, use garbage
|
||||
collected strings. */
|
||||
VEC_truncate (const_char_p, optimize_args, 0);
|
||||
VEC_safe_push (const_char_p, gc, optimize_args, NULL);
|
||||
|
||||
for (ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
|
||||
{
|
||||
tree value = TREE_VALUE (ap);
|
||||
|
||||
if (TREE_CODE (value) == INTEGER_CST)
|
||||
{
|
||||
char buffer[20];
|
||||
sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
|
||||
VEC_safe_push (const_char_p, gc, optimize_args, ggc_strdup (buffer));
|
||||
}
|
||||
|
||||
else if (TREE_CODE (value) == STRING_CST)
|
||||
{
|
||||
/* Split string into multiple substrings. */
|
||||
size_t len = TREE_STRING_LENGTH (value);
|
||||
char *p = ASTRDUP (TREE_STRING_POINTER (value));
|
||||
char *end = p + len;
|
||||
char *comma;
|
||||
char *next_p = p;
|
||||
|
||||
while (next_p != NULL)
|
||||
{
|
||||
size_t len2;
|
||||
char *q, *r;
|
||||
|
||||
p = next_p;
|
||||
comma = strchr (p, ',');
|
||||
if (comma)
|
||||
{
|
||||
len2 = comma - p;
|
||||
*comma = '\0';
|
||||
next_p = comma+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len2 = end - p;
|
||||
next_p = NULL;
|
||||
}
|
||||
|
||||
r = q = (char *) ggc_alloc (len2 + 3);
|
||||
|
||||
/* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
|
||||
options. */
|
||||
if (*p == '-' && p[1] != 'O' && p[1] != 'f')
|
||||
{
|
||||
ret = false;
|
||||
if (attr_p)
|
||||
warning (OPT_Wattributes,
|
||||
"Bad option %s to optimize attribute.", p);
|
||||
else
|
||||
warning (OPT_Wpragmas,
|
||||
"Bad option %s to pragma attribute", p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*p != '-')
|
||||
{
|
||||
*r++ = '-';
|
||||
|
||||
/* Assume that Ox is -Ox, a numeric value is -Ox, a s by
|
||||
itself is -Os, and any other switch begins with a -f. */
|
||||
if ((*p >= '0' && *p <= '9')
|
||||
|| (p[0] == 's' && p[1] == '\0'))
|
||||
*r++ = 'O';
|
||||
else if (*p != 'O')
|
||||
*r++ = 'f';
|
||||
}
|
||||
|
||||
memcpy (r, p, len2);
|
||||
r[len2] = '\0';
|
||||
VEC_safe_push (const_char_p, gc, optimize_args, q);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
opt_argc = VEC_length (const_char_p, optimize_args);
|
||||
opt_argv = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
|
||||
|
||||
for (i = 1; i < opt_argc; i++)
|
||||
opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
|
||||
|
||||
/* Now parse the options. */
|
||||
decode_options (opt_argc, opt_argv);
|
||||
|
||||
VEC_truncate (const_char_p, optimize_args, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* For handling "optimize" attribute. arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_optimize_attribute (tree *node, tree name, tree args,
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
{
|
||||
/* Ensure we have a function type. */
|
||||
if (TREE_CODE (*node) != FUNCTION_DECL)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct cl_optimization cur_opts;
|
||||
tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
|
||||
|
||||
/* Save current options. */
|
||||
cl_optimization_save (&cur_opts);
|
||||
|
||||
/* If we previously had some optimization options, use them as the
|
||||
default. */
|
||||
if (old_opts)
|
||||
cl_optimization_restore (TREE_OPTIMIZATION (old_opts));
|
||||
|
||||
/* Parse options, and update the vector. */
|
||||
parse_optimize_options (args, true);
|
||||
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
|
||||
= build_optimization_node ();
|
||||
|
||||
/* Restore current options. */
|
||||
cl_optimization_restore (&cur_opts);
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Check for valid arguments being passed to a function.
|
||||
ATTRS is a list of attributes. There are NARGS arguments in the array
|
||||
|
|
|
@ -870,6 +870,7 @@ extern tree c_staticp (tree);
|
|||
extern void init_c_lex (void);
|
||||
|
||||
extern void c_cpp_builtins (cpp_reader *);
|
||||
extern void c_cpp_builtins_optimize_pragma (cpp_reader *, tree, tree);
|
||||
|
||||
/* Positive if an implicit `extern "C"' scope has just been entered;
|
||||
negative if such a scope has just been exited. */
|
||||
|
@ -925,7 +926,6 @@ extern void warn_about_parentheses (enum tree_code, enum tree_code,
|
|||
extern void warn_for_unused_label (tree label);
|
||||
extern void warn_for_div_by_zero (tree divisor);
|
||||
|
||||
|
||||
/* In c-gimplify.c */
|
||||
extern void c_genericize (tree);
|
||||
extern int c_gimplify_expr (tree *, tree *, tree *);
|
||||
|
@ -944,6 +944,8 @@ extern void c_common_print_pch_checksum (FILE *f);
|
|||
/* In *-checksum.c */
|
||||
extern const unsigned char executable_checksum[16];
|
||||
|
||||
/* In c-cppbuiltin.c */
|
||||
extern void builtin_define_std (const char *macro);
|
||||
extern void builtin_define_with_value (const char *, const char *, int);
|
||||
extern void c_stddef_cpp_builtins (void);
|
||||
extern void fe_file_change (const struct line_map *);
|
||||
|
|
|
@ -405,6 +405,58 @@ builtin_define_stdint_macros (void)
|
|||
builtin_define_type_max ("__INTMAX_MAX__", intmax_type_node, intmax_long);
|
||||
}
|
||||
|
||||
/* Adjust the optimization macros when a #pragma GCC optimization is done to
|
||||
reflect the current level. */
|
||||
void
|
||||
c_cpp_builtins_optimize_pragma (cpp_reader *pfile, tree prev_tree,
|
||||
tree cur_tree)
|
||||
{
|
||||
struct cl_optimization *prev = TREE_OPTIMIZATION (prev_tree);
|
||||
struct cl_optimization *cur = TREE_OPTIMIZATION (cur_tree);
|
||||
bool prev_fast_math;
|
||||
bool cur_fast_math;
|
||||
|
||||
/* -undef turns off target-specific built-ins. */
|
||||
if (flag_undef)
|
||||
return;
|
||||
|
||||
/* Other target-independent built-ins determined by command-line
|
||||
options. */
|
||||
if (!prev->optimize_size && cur->optimize_size)
|
||||
cpp_define (pfile, "__OPTIMIZE_SIZE__");
|
||||
else if (prev->optimize_size && !cur->optimize_size)
|
||||
cpp_undef (pfile, "__OPTIMIZE_SIZE__");
|
||||
|
||||
if (!prev->optimize && cur->optimize)
|
||||
cpp_define (pfile, "__OPTIMIZE__");
|
||||
else if (prev->optimize && !cur->optimize)
|
||||
cpp_undef (pfile, "__OPTIMIZE__");
|
||||
|
||||
prev_fast_math = fast_math_flags_struct_set_p (prev);
|
||||
cur_fast_math = fast_math_flags_struct_set_p (cur);
|
||||
if (!prev_fast_math && cur_fast_math)
|
||||
cpp_define (pfile, "__FAST_MATH__");
|
||||
else if (prev_fast_math && !cur_fast_math)
|
||||
cpp_undef (pfile, "__FAST_MATH__");
|
||||
|
||||
if (!prev->flag_signaling_nans && cur->flag_signaling_nans)
|
||||
cpp_define (pfile, "__SUPPORT_SNAN__");
|
||||
else if (prev->flag_signaling_nans && !cur->flag_signaling_nans)
|
||||
cpp_undef (pfile, "__SUPPORT_SNAN__");
|
||||
|
||||
if (!prev->flag_finite_math_only && cur->flag_finite_math_only)
|
||||
{
|
||||
cpp_undef (pfile, "__FINITE_MATH_ONLY__");
|
||||
cpp_define (pfile, "__FINITE_MATH_ONLY__=1");
|
||||
}
|
||||
else if (!prev->flag_finite_math_only && cur->flag_finite_math_only)
|
||||
{
|
||||
cpp_undef (pfile, "__FINITE_MATH_ONLY__");
|
||||
cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Hook that registers front end and target-specific built-ins. */
|
||||
void
|
||||
c_cpp_builtins (cpp_reader *pfile)
|
||||
|
|
11
gcc/c-decl.c
11
gcc/c-decl.c
|
@ -1842,6 +1842,17 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|
|||
= C_DECL_BUILTIN_PROTOTYPE (olddecl);
|
||||
}
|
||||
|
||||
/* Preserve function specific target and optimization options */
|
||||
if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl)
|
||||
&& !DECL_FUNCTION_SPECIFIC_TARGET (newdecl))
|
||||
DECL_FUNCTION_SPECIFIC_TARGET (newdecl)
|
||||
= DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
|
||||
|
||||
if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl)
|
||||
&& !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
|
||||
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
|
||||
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
|
||||
|
||||
/* Also preserve various other info from the definition. */
|
||||
if (!new_is_definition)
|
||||
{
|
||||
|
|
309
gcc/c-pragma.c
309
gcc/c-pragma.c
|
@ -866,6 +866,313 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
|
|||
GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
|
||||
}
|
||||
|
||||
/* Stack of the #pragma GCC options created with #pragma GCC option push. */
|
||||
static GTY(()) VEC(tree,gc) *option_stack;
|
||||
|
||||
/* Parse #pragma GCC option (xxx) to set target specific options. */
|
||||
static void
|
||||
handle_pragma_option(cpp_reader *ARG_UNUSED(dummy))
|
||||
{
|
||||
enum cpp_ttype token;
|
||||
const char *name;
|
||||
tree x;
|
||||
bool close_paren_needed_p = false;
|
||||
|
||||
if (cfun)
|
||||
{
|
||||
error ("#pragma GCC option is not allowed inside functions");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetm.target_option.pragma_parse)
|
||||
{
|
||||
error ("#pragma GCC option is not supported for this system");
|
||||
return;
|
||||
}
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (token == CPP_OPEN_PAREN)
|
||||
{
|
||||
close_paren_needed_p = true;
|
||||
token = pragma_lex (&x);
|
||||
}
|
||||
|
||||
if (token == CPP_NAME)
|
||||
{
|
||||
bool call_pragma_parse_p = false;
|
||||
bool ok_p;
|
||||
|
||||
name = IDENTIFIER_POINTER (x);
|
||||
if (strcmp (name, "reset") == 0)
|
||||
{
|
||||
current_option_pragma = NULL_TREE;
|
||||
call_pragma_parse_p = true;
|
||||
}
|
||||
|
||||
else if (strcmp (name, "push") == 0)
|
||||
VEC_safe_push (tree, gc, option_stack,
|
||||
copy_list (current_option_pragma));
|
||||
|
||||
else if (strcmp (name, "pop") == 0)
|
||||
{
|
||||
int len = VEC_length (tree, option_stack);
|
||||
if (len == 0)
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC option pop%> without a %<#pragma GCC "
|
||||
"option push%>");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
VEC_truncate (tree, option_stack, len-1);
|
||||
current_option_pragma = ((len > 1)
|
||||
? VEC_last (tree, option_stack)
|
||||
: NULL_TREE);
|
||||
|
||||
call_pragma_parse_p = true;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC option%> is not a string or "
|
||||
"push/pop/reset");
|
||||
return;
|
||||
}
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (close_paren_needed_p)
|
||||
{
|
||||
if (token == CPP_CLOSE_PAREN)
|
||||
token = pragma_lex (&x);
|
||||
else
|
||||
GCC_BAD ("%<#pragma GCC option ([push|pop|reset])%> does not "
|
||||
"have a final %<)%>.");
|
||||
}
|
||||
|
||||
if (token != CPP_EOF)
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC option [push|pop|reset]%> is badly "
|
||||
"formed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if we need to call the pragma_parse hook. This must occur at the
|
||||
end after processing all of the tokens, or we may get spurious errors
|
||||
when we define or undef macros. */
|
||||
ok_p = targetm.target_option.pragma_parse (current_option_pragma);
|
||||
gcc_assert (ok_p);
|
||||
}
|
||||
|
||||
else if (token != CPP_STRING)
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC option%> is not a string or push/pop/reset");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Strings are user options. */
|
||||
else
|
||||
{
|
||||
tree args = NULL_TREE;
|
||||
|
||||
do
|
||||
{
|
||||
/* Build up the strings now as a tree linked list. Skip empty
|
||||
strings. */
|
||||
if (TREE_STRING_LENGTH (x) > 0)
|
||||
args = tree_cons (NULL_TREE, x, args);
|
||||
|
||||
token = pragma_lex (&x);
|
||||
while (token == CPP_COMMA)
|
||||
token = pragma_lex (&x);
|
||||
}
|
||||
while (token == CPP_STRING);
|
||||
|
||||
if (close_paren_needed_p)
|
||||
{
|
||||
if (token == CPP_CLOSE_PAREN)
|
||||
token = pragma_lex (&x);
|
||||
else
|
||||
GCC_BAD ("%<#pragma GCC option (string [,string]...)%> does "
|
||||
"not have a final %<)%>.");
|
||||
}
|
||||
|
||||
if (token != CPP_EOF)
|
||||
{
|
||||
error ("#pragma GCC option string... is badly formed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* put arguments in the order the user typed them. */
|
||||
args = nreverse (args);
|
||||
|
||||
if (targetm.target_option.pragma_parse (args))
|
||||
current_option_pragma = args;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stack of the #pragma GCC optimize options created with #pragma GCC optimize
|
||||
push. */
|
||||
static GTY(()) VEC(tree,gc) *optimize_stack;
|
||||
|
||||
/* Handle #pragma GCC optimize to set optimization options. */
|
||||
static void
|
||||
handle_pragma_optimize(cpp_reader *ARG_UNUSED(dummy))
|
||||
{
|
||||
enum cpp_ttype token;
|
||||
const char *name;
|
||||
tree x;
|
||||
bool close_paren_needed_p = false;
|
||||
tree optimization_previous_node = optimization_current_node;
|
||||
|
||||
if (cfun)
|
||||
{
|
||||
error ("#pragma GCC optimize is not allowed inside functions");
|
||||
return;
|
||||
}
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (token == CPP_OPEN_PAREN)
|
||||
{
|
||||
close_paren_needed_p = true;
|
||||
token = pragma_lex (&x);
|
||||
}
|
||||
|
||||
if (token == CPP_NAME)
|
||||
{
|
||||
bool call_opt_p = false;
|
||||
|
||||
name = IDENTIFIER_POINTER (x);
|
||||
if (strcmp (name, "reset") == 0)
|
||||
{
|
||||
struct cl_optimization *def
|
||||
= TREE_OPTIMIZATION (optimization_default_node);
|
||||
current_optimize_pragma = NULL_TREE;
|
||||
optimization_current_node = optimization_default_node;
|
||||
cl_optimization_restore (def);
|
||||
call_opt_p = true;
|
||||
}
|
||||
|
||||
else if (strcmp (name, "push") == 0)
|
||||
VEC_safe_push (tree, gc, optimize_stack, current_optimize_pragma);
|
||||
|
||||
else if (strcmp (name, "pop") == 0)
|
||||
{
|
||||
int len = VEC_length (tree, optimize_stack);
|
||||
if (len == 0)
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC optimize pop%> without a %<#pragma "
|
||||
"GCC optimize push%>");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
VEC_truncate (tree, optimize_stack, len-1);
|
||||
current_optimize_pragma
|
||||
= ((len > 1)
|
||||
? VEC_last (tree, optimize_stack)
|
||||
: NULL_TREE);
|
||||
|
||||
call_opt_p = true;
|
||||
if (current_optimize_pragma)
|
||||
{
|
||||
bool ok_p
|
||||
= parse_optimize_options (current_optimize_pragma, false);
|
||||
gcc_assert (ok_p); /* should be parsed previously. */
|
||||
optimization_current_node = build_optimization_node ();
|
||||
}
|
||||
else
|
||||
{
|
||||
struct cl_optimization *opt
|
||||
= TREE_OPTIMIZATION (optimization_default_node);
|
||||
optimization_current_node = optimization_default_node;
|
||||
cl_optimization_restore (opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC optimize%> is not a string or "
|
||||
"push/pop/reset");
|
||||
return;
|
||||
}
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (close_paren_needed_p)
|
||||
{
|
||||
if (token == CPP_CLOSE_PAREN)
|
||||
token = pragma_lex (&x);
|
||||
else
|
||||
GCC_BAD ("%<#pragma GCC optimize ([push|pop|reset])%> does not "
|
||||
"have a final %<)%>.");
|
||||
}
|
||||
|
||||
if (token != CPP_EOF)
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC optimize [push|pop|reset]%> is badly "
|
||||
"formed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (call_opt_p &&
|
||||
(optimization_previous_node != optimization_current_node))
|
||||
c_cpp_builtins_optimize_pragma (parse_in,
|
||||
optimization_previous_node,
|
||||
optimization_current_node);
|
||||
|
||||
}
|
||||
|
||||
else if (token != CPP_STRING && token != CPP_NUMBER)
|
||||
{
|
||||
GCC_BAD ("%<#pragma GCC optimize%> is not a string, number, or "
|
||||
"push/pop/reset");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Strings/numbers are user options. */
|
||||
else
|
||||
{
|
||||
tree args = NULL_TREE;
|
||||
|
||||
do
|
||||
{
|
||||
/* Build up the numbers/strings now as a list. */
|
||||
if (token != CPP_STRING || TREE_STRING_LENGTH (x) > 0)
|
||||
args = tree_cons (NULL_TREE, x, args);
|
||||
|
||||
token = pragma_lex (&x);
|
||||
while (token == CPP_COMMA)
|
||||
token = pragma_lex (&x);
|
||||
}
|
||||
while (token == CPP_STRING || token == CPP_NUMBER);
|
||||
|
||||
if (close_paren_needed_p)
|
||||
{
|
||||
if (token == CPP_CLOSE_PAREN)
|
||||
token = pragma_lex (&x);
|
||||
else
|
||||
GCC_BAD ("%<#pragma GCC optimize (string [,string]...)%> does "
|
||||
"not have a final %<)%>.");
|
||||
}
|
||||
|
||||
if (token != CPP_EOF)
|
||||
{
|
||||
error ("#pragma GCC optimize string... is badly formed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* put arguments in the order the user typed them. */
|
||||
args = nreverse (args);
|
||||
|
||||
parse_optimize_options (args, false);
|
||||
optimization_current_node = build_optimization_node ();
|
||||
c_cpp_builtins_optimize_pragma (parse_in,
|
||||
optimization_previous_node,
|
||||
optimization_current_node);
|
||||
}
|
||||
}
|
||||
|
||||
/* A vector of registered pragma callbacks. */
|
||||
|
||||
DEF_VEC_O (pragma_handler);
|
||||
|
@ -1028,6 +1335,8 @@ init_pragma (void)
|
|||
#endif
|
||||
|
||||
c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
|
||||
c_register_pragma ("GCC", "option", handle_pragma_option);
|
||||
c_register_pragma ("GCC", "optimize", handle_pragma_optimize);
|
||||
|
||||
c_register_pragma_with_expansion (0, "redefine_extname", handle_pragma_redefine_extname);
|
||||
c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
|
||||
|
|
|
@ -59,11 +59,11 @@ Common Joined Separate UInteger
|
|||
-G<number> Put global and static data smaller than <number> bytes into a special section (on some targets)
|
||||
|
||||
O
|
||||
Common JoinedOrMissing
|
||||
Common JoinedOrMissing Optimization
|
||||
-O<number> Set optimization level to <number>
|
||||
|
||||
Os
|
||||
Common
|
||||
Common Optimization
|
||||
Optimize for space rather than speed
|
||||
|
||||
W
|
||||
|
@ -275,28 +275,28 @@ fabi-version=
|
|||
Common Joined UInteger Var(flag_abi_version) Init(2)
|
||||
|
||||
falign-functions
|
||||
Common Report Var(align_functions,0)
|
||||
Common Report Var(align_functions,0) Optimization UInteger
|
||||
Align the start of functions
|
||||
|
||||
falign-functions=
|
||||
Common RejectNegative Joined UInteger
|
||||
|
||||
falign-jumps
|
||||
Common Report Var(align_jumps,0) Optimization
|
||||
Common Report Var(align_jumps,0) Optimization UInteger
|
||||
Align labels which are only reached by jumping
|
||||
|
||||
falign-jumps=
|
||||
Common RejectNegative Joined UInteger
|
||||
|
||||
falign-labels
|
||||
Common Report Var(align_labels,0) Optimization
|
||||
Common Report Var(align_labels,0) Optimization UInteger
|
||||
Align all labels
|
||||
|
||||
falign-labels=
|
||||
Common RejectNegative Joined UInteger
|
||||
|
||||
falign-loops
|
||||
Common Report Var(align_loops) Optimization
|
||||
Common Report Var(align_loops) Optimization UInteger
|
||||
Align the start of loops
|
||||
|
||||
falign-loops=
|
||||
|
@ -666,7 +666,7 @@ Common
|
|||
Does nothing. Preserved for backward compatibility.
|
||||
|
||||
fmath-errno
|
||||
Common Report Var(flag_errno_math) Init(1)
|
||||
Common Report Var(flag_errno_math) Init(1) Optimization
|
||||
Set errno after built-in math functions
|
||||
|
||||
fmem-report
|
||||
|
@ -925,7 +925,7 @@ Reschedule instructions after register allocation
|
|||
; sched_stalled_insns means that insns can be moved prematurely from the queue
|
||||
; of stalled insns into the ready list.
|
||||
fsched-stalled-insns
|
||||
Common Report Var(flag_sched_stalled_insns) Optimization
|
||||
Common Report Var(flag_sched_stalled_insns) Optimization UInteger
|
||||
Allow premature scheduling of queued insns
|
||||
|
||||
fsched-stalled-insns=
|
||||
|
@ -937,7 +937,7 @@ Common RejectNegative Joined UInteger
|
|||
; premature removal from the queue of stalled insns into the ready list (has
|
||||
; an effect only if the flag 'sched_stalled_insns' is set).
|
||||
fsched-stalled-insns-dep
|
||||
Common Report Var(flag_sched_stalled_insns_dep,1) Init(1) Optimization
|
||||
Common Report Var(flag_sched_stalled_insns_dep,1) Init(1) Optimization UInteger
|
||||
Set dependence distance checking in premature scheduling of queued insns
|
||||
|
||||
fsched-stalled-insns-dep=
|
||||
|
|
|
@ -294,6 +294,8 @@ fido-*-*)
|
|||
;;
|
||||
i[34567]86-*-*)
|
||||
cpu_type=i386
|
||||
c_target_objs="i386-c.o"
|
||||
cxx_target_objs="i386-c.o"
|
||||
extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h
|
||||
pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h
|
||||
nmmintrin.h bmmintrin.h mmintrin-common.h
|
||||
|
@ -301,6 +303,8 @@ i[34567]86-*-*)
|
|||
;;
|
||||
x86_64-*-*)
|
||||
cpu_type=i386
|
||||
c_target_objs="i386-c.o"
|
||||
cxx_target_objs="i386-c.o"
|
||||
extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h
|
||||
pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h
|
||||
nmmintrin.h bmmintrin.h mmintrin-common.h
|
||||
|
@ -410,8 +414,8 @@ case ${target} in
|
|||
tmake_file="t-darwin ${cpu_type}/t-darwin t-slibgcc-darwin"
|
||||
target_gtfiles="\$(srcdir)/config/darwin.c"
|
||||
extra_options="${extra_options} darwin.opt"
|
||||
c_target_objs="darwin-c.o"
|
||||
cxx_target_objs="darwin-c.o"
|
||||
c_target_objs="${c_target_objs} darwin-c.o"
|
||||
cxx_target_objs="${cxx_target_objs} darwin-c.o"
|
||||
fortran_target_objs="darwin-f.o"
|
||||
extra_objs="darwin.o"
|
||||
extra_gcc_objs="darwin-driver.o"
|
||||
|
@ -1028,16 +1032,16 @@ i[34567]86-*-darwin*)
|
|||
;;
|
||||
x86_64-*-darwin*)
|
||||
with_cpu=${with_cpu:-generic}
|
||||
tmake_file="t-darwin ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
|
||||
tmake_file="${tmake_file} t-darwin ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
|
||||
tm_file="${tm_file} ${cpu_type}/darwin64.h"
|
||||
;;
|
||||
i[34567]86-*-elf*)
|
||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h"
|
||||
tmake_file="i386/t-i386elf t-svr4"
|
||||
tmake_file="${tmake_file} i386/t-i386elf t-svr4"
|
||||
;;
|
||||
x86_64-*-elf*)
|
||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/x86-64.h"
|
||||
tmake_file="i386/t-i386elf t-svr4"
|
||||
tmake_file="${tmake_file} i386/t-i386elf t-svr4"
|
||||
;;
|
||||
i[34567]86-*-aout*)
|
||||
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/i386-aout.h"
|
||||
|
@ -1054,7 +1058,7 @@ i[34567]86-*-netbsdelf*)
|
|||
;;
|
||||
i[34567]86-*-netbsd*)
|
||||
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h netbsd.h netbsd-aout.h i386/netbsd.h"
|
||||
tmake_file=t-netbsd
|
||||
tmake_file="${tmake_file} t-netbsd"
|
||||
extra_parts=""
|
||||
use_collect2=yes
|
||||
;;
|
||||
|
@ -1065,7 +1069,7 @@ x86_64-*-netbsd*)
|
|||
i[34567]86-*-openbsd2.*|i[34567]86-*openbsd3.[0123])
|
||||
tm_file="i386/i386.h i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h openbsd-oldgas.h openbsd.h i386/openbsd.h"
|
||||
# needed to unconfuse gdb
|
||||
tmake_file="t-libc-ok t-openbsd i386/t-openbsd"
|
||||
tmake_file="${tmake_file} t-libc-ok t-openbsd i386/t-openbsd"
|
||||
# we need collect2 until our bug is fixed...
|
||||
use_collect2=yes
|
||||
;;
|
||||
|
@ -1126,7 +1130,7 @@ i[34567]86-*-gnu*)
|
|||
i[34567]86-pc-msdosdjgpp*)
|
||||
xm_file=i386/xm-djgpp.h
|
||||
tm_file="dbxcoff.h ${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h"
|
||||
tmake_file=i386/t-djgpp
|
||||
tmake_file="${tmake_file} i386/t-djgpp"
|
||||
extra_options="${extra_options} i386/djgpp.opt"
|
||||
gnu_ld=yes
|
||||
gas=yes
|
||||
|
@ -1134,7 +1138,7 @@ i[34567]86-pc-msdosdjgpp*)
|
|||
i[34567]86-*-lynxos*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/lynx.h lynx.h"
|
||||
tmake_file="i386/t-crtstuff t-lynx"
|
||||
tmake_file="${tmake_file} i386/t-crtstuff t-lynx"
|
||||
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
|
||||
extra_options="${extra_options} lynx.opt"
|
||||
thread_file=lynx
|
||||
|
@ -1143,7 +1147,7 @@ i[34567]86-*-lynxos*)
|
|||
;;
|
||||
i[3456x]86-*-netware*)
|
||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h tm-dwarf2.h i386/netware.h"
|
||||
tmake_file=i386/t-netware
|
||||
tmake_file="${tmake_file} i386/t-netware"
|
||||
extra_objs=netware.o
|
||||
case /${with_ld} in
|
||||
*/nwld)
|
||||
|
@ -1162,14 +1166,14 @@ i[3456x]86-*-netware*)
|
|||
;;
|
||||
i[34567]86-*-nto-qnx*)
|
||||
tm_file="${tm_file} i386/att.h dbxelf.h tm-dwarf2.h elfos.h svr4.h i386/unix.h i386/nto.h"
|
||||
tmake_file=i386/t-nto
|
||||
tmake_file="${tmake_file} i386/t-nto"
|
||||
gnu_ld=yes
|
||||
gas=yes
|
||||
;;
|
||||
i[34567]86-*-rtems*)
|
||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h"
|
||||
extra_parts="crtbegin.o crtend.o crti.o crtn.o"
|
||||
tmake_file="i386/t-rtems-i386 i386/t-crtstuff t-rtems"
|
||||
tmake_file="${tmake_file} i386/t-rtems-i386 i386/t-crtstuff t-rtems"
|
||||
;;
|
||||
i[34567]86-*-solaris2*)
|
||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h sol2.h"
|
||||
|
@ -1179,9 +1183,9 @@ i[34567]86-*-solaris2*)
|
|||
;;
|
||||
esac
|
||||
tm_file="${tm_file} i386/sol2.h"
|
||||
tmake_file="t-sol2 i386/t-sol2 t-svr4"
|
||||
c_target_objs="sol2-c.o"
|
||||
cxx_target_objs="sol2-c.o"
|
||||
tmake_file="${tmake_file} t-sol2 i386/t-sol2 t-svr4"
|
||||
c_target_objs="${c_target_objs} sol2-c.o"
|
||||
cxx_target_objs="${cxx_target_objs} sol2-c.o"
|
||||
extra_objs="sol2.o"
|
||||
tm_p_file="${tm_p_file} sol2-protos.h"
|
||||
if test x$gnu_ld = xyes; then
|
||||
|
@ -1247,12 +1251,12 @@ i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae)
|
|||
i[34567]86-*-pe | i[34567]86-*-cygwin*)
|
||||
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h"
|
||||
xm_file=i386/xm-cygwin.h
|
||||
tmake_file="i386/t-cygwin i386/t-cygming"
|
||||
tmake_file="${tmake_file} i386/t-cygwin i386/t-cygming"
|
||||
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
|
||||
extra_options="${extra_options} i386/cygming.opt"
|
||||
extra_objs="winnt.o winnt-stubs.o"
|
||||
c_target_objs="cygwin2.o msformat-c.o"
|
||||
cxx_target_objs="cygwin2.o winnt-cxx.o msformat-c.o"
|
||||
c_target_objs="${c_target_objs} cygwin2.o msformat-c.o"
|
||||
cxx_target_objs="${cxx_target_objs} cygwin2.o winnt-cxx.o msformat-c.o"
|
||||
extra_gcc_objs=cygwin1.o
|
||||
if test x$enable_threads = xyes; then
|
||||
thread_file='posix'
|
||||
|
@ -1261,12 +1265,12 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
|
|||
i[34567]86-*-mingw* | x86_64-*-mingw*)
|
||||
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
|
||||
xm_file=i386/xm-mingw32.h
|
||||
tmake_file="i386/t-cygming i386/t-mingw32"
|
||||
tmake_file="${tmake_file} i386/t-cygming i386/t-mingw32"
|
||||
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
|
||||
extra_options="${extra_options} i386/cygming.opt"
|
||||
extra_objs="winnt.o winnt-stubs.o"
|
||||
c_target_objs="msformat-c.o"
|
||||
cxx_target_objs="winnt-cxx.o msformat-c.o"
|
||||
c_target_objs="${c_target_objs} msformat-c.o"
|
||||
cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
|
||||
default_use_cxa_atexit=yes
|
||||
case ${enable_threads} in
|
||||
"" | yes | win32)
|
||||
|
@ -1291,7 +1295,7 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
|
|||
;;
|
||||
i[34567]86-*-interix3*)
|
||||
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/i386-interix.h i386/i386-interix3.h interix.h interix3.h"
|
||||
tmake_file="i386/t-interix"
|
||||
tmake_file="${tmake_file} i386/t-interix"
|
||||
extra_objs=winnt.o
|
||||
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
|
||||
if test x$enable_threads = xyes ; then
|
||||
|
@ -2369,10 +2373,10 @@ esac
|
|||
|
||||
case ${target} in
|
||||
i[34567]86-*-linux* | x86_64-*-linux*)
|
||||
tmake_file="${tmake_file} i386/t-pmm_malloc"
|
||||
tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
|
||||
;;
|
||||
i[34567]86-*-* | x86_64-*-*)
|
||||
tmake_file="${tmake_file} i386/t-gmm_malloc"
|
||||
tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
@ -263,8 +263,8 @@ extern void darwin_x86_file_end (void);
|
|||
: (n) >= 11 && (n) <= 18 ? (n) + 1 \
|
||||
: (n))
|
||||
|
||||
#undef REGISTER_TARGET_PRAGMAS
|
||||
#define REGISTER_TARGET_PRAGMAS() DARWIN_REGISTER_TARGET_PRAGMAS()
|
||||
#undef REGISTER_SUBTARGET_PRAGMAS
|
||||
#define REGISTER_SUBTARGET_PRAGMAS() DARWIN_REGISTER_TARGET_PRAGMAS()
|
||||
|
||||
#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
|
||||
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES darwin_set_default_type_attributes
|
||||
|
|
344
gcc/config/i386/i386-c.c
Normal file
344
gcc/config/i386/i386-c.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/* Subroutines used for macro/preprocessor support on the ia-32.
|
||||
Copyright (C) 2008
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "rtl.h"
|
||||
#include "tree.h"
|
||||
#include "tm_p.h"
|
||||
#include "flags.h"
|
||||
#include "c-common.h"
|
||||
#include "ggc.h"
|
||||
#include "target.h"
|
||||
#include "target-def.h"
|
||||
#include "cpplib.h"
|
||||
#include "c-pragma.h"
|
||||
|
||||
static bool ix86_pragma_option_parse (tree);
|
||||
static void ix86_target_macros_internal
|
||||
(int, enum processor_type, enum processor_type, enum fpmath_unit,
|
||||
void (*def_or_undef) (cpp_reader *, const char *));
|
||||
|
||||
|
||||
/* Internal function to either define or undef the appropriate system
|
||||
macros. */
|
||||
static void
|
||||
ix86_target_macros_internal (int isa_flag,
|
||||
enum processor_type arch,
|
||||
enum processor_type tune,
|
||||
enum fpmath_unit fpmath,
|
||||
void (*def_or_undef) (cpp_reader *,
|
||||
const char *))
|
||||
{
|
||||
/* For some of the k6/pentium varients there weren't seperate ISA bits to
|
||||
identify which tune/arch flag was passed, so figure it out here. */
|
||||
size_t arch_len = strlen (ix86_arch_string);
|
||||
size_t tune_len = strlen (ix86_tune_string);
|
||||
int last_arch_char = ix86_arch_string[arch_len - 1];
|
||||
int last_tune_char = ix86_tune_string[tune_len - 1];
|
||||
|
||||
/* Built-ins based on -march=. */
|
||||
switch (arch)
|
||||
{
|
||||
case PROCESSOR_I386:
|
||||
break;
|
||||
case PROCESSOR_I486:
|
||||
def_or_undef (parse_in, "__i486");
|
||||
def_or_undef (parse_in, "__i486__");
|
||||
break;
|
||||
case PROCESSOR_PENTIUM:
|
||||
def_or_undef (parse_in, "__i586");
|
||||
def_or_undef (parse_in, "__i586__");
|
||||
def_or_undef (parse_in, "__pentium");
|
||||
def_or_undef (parse_in, "__pentium__");
|
||||
if (isa_flag & OPTION_MASK_ISA_MMX)
|
||||
def_or_undef (parse_in, "__pentium_mmx__");
|
||||
break;
|
||||
case PROCESSOR_PENTIUMPRO:
|
||||
def_or_undef (parse_in, "__i686");
|
||||
def_or_undef (parse_in, "__i686__");
|
||||
def_or_undef (parse_in, "__pentiumpro");
|
||||
def_or_undef (parse_in, "__pentiumpro__");
|
||||
break;
|
||||
case PROCESSOR_GEODE:
|
||||
def_or_undef (parse_in, "__geode");
|
||||
def_or_undef (parse_in, "__geode__");
|
||||
break;
|
||||
case PROCESSOR_K6:
|
||||
def_or_undef (parse_in, "__k6");
|
||||
def_or_undef (parse_in, "__k6__");
|
||||
if (last_arch_char == '2')
|
||||
def_or_undef (parse_in, "__k6_2__");
|
||||
else if (last_arch_char == '3')
|
||||
def_or_undef (parse_in, "__k6_3__");
|
||||
else if (isa_flag & OPTION_MASK_ISA_3DNOW)
|
||||
def_or_undef (parse_in, "__k6_3__");
|
||||
break;
|
||||
case PROCESSOR_ATHLON:
|
||||
def_or_undef (parse_in, "__athlon");
|
||||
def_or_undef (parse_in, "__athlon__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE)
|
||||
def_or_undef (parse_in, "__athlon_sse__");
|
||||
break;
|
||||
case PROCESSOR_K8:
|
||||
def_or_undef (parse_in, "__k8");
|
||||
def_or_undef (parse_in, "__k8__");
|
||||
break;
|
||||
case PROCESSOR_AMDFAM10:
|
||||
def_or_undef (parse_in, "__amdfam10");
|
||||
def_or_undef (parse_in, "__amdfam10__");
|
||||
break;
|
||||
case PROCESSOR_PENTIUM4:
|
||||
def_or_undef (parse_in, "__pentium4");
|
||||
def_or_undef (parse_in, "__pentium4__");
|
||||
break;
|
||||
case PROCESSOR_NOCONA:
|
||||
def_or_undef (parse_in, "__nocona");
|
||||
def_or_undef (parse_in, "__nocona__");
|
||||
break;
|
||||
case PROCESSOR_CORE2:
|
||||
def_or_undef (parse_in, "__core2");
|
||||
def_or_undef (parse_in, "__core2__");
|
||||
break;
|
||||
/* use PROCESSOR_max to not set/unset the arch macro. */
|
||||
case PROCESSOR_max:
|
||||
break;
|
||||
case PROCESSOR_GENERIC32:
|
||||
case PROCESSOR_GENERIC64:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Built-ins based on -mtune=. */
|
||||
switch (tune)
|
||||
{
|
||||
case PROCESSOR_I386:
|
||||
def_or_undef (parse_in, "__tune_i386__");
|
||||
break;
|
||||
case PROCESSOR_I486:
|
||||
def_or_undef (parse_in, "__tune_i486__");
|
||||
break;
|
||||
case PROCESSOR_PENTIUM:
|
||||
def_or_undef (parse_in, "__tune_i586__");
|
||||
def_or_undef (parse_in, "__tune_pentium__");
|
||||
if (last_tune_char == 'x')
|
||||
def_or_undef (parse_in, "__tune_pentium_mmx__");
|
||||
break;
|
||||
case PROCESSOR_PENTIUMPRO:
|
||||
def_or_undef (parse_in, "__tune_i686__");
|
||||
def_or_undef (parse_in, "__tune_pentiumpro__");
|
||||
switch (last_tune_char)
|
||||
{
|
||||
case '3':
|
||||
def_or_undef (parse_in, "__tune_pentium3__");
|
||||
/* FALLTHRU */
|
||||
case '2':
|
||||
def_or_undef (parse_in, "__tune_pentium2__");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PROCESSOR_GEODE:
|
||||
def_or_undef (parse_in, "__tune_geode__");
|
||||
break;
|
||||
case PROCESSOR_K6:
|
||||
def_or_undef (parse_in, "__tune_k6__");
|
||||
if (last_tune_char == '2')
|
||||
def_or_undef (parse_in, "__tune_k6_2__");
|
||||
else if (last_tune_char == '3')
|
||||
def_or_undef (parse_in, "__tune_k6_3__");
|
||||
else if (isa_flag & OPTION_MASK_ISA_3DNOW)
|
||||
def_or_undef (parse_in, "__tune_k6_3__");
|
||||
break;
|
||||
case PROCESSOR_ATHLON:
|
||||
def_or_undef (parse_in, "__tune_athlon__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE)
|
||||
def_or_undef (parse_in, "__tune_athlon_sse__");
|
||||
break;
|
||||
case PROCESSOR_K8:
|
||||
def_or_undef (parse_in, "__tune_k8__");
|
||||
break;
|
||||
case PROCESSOR_AMDFAM10:
|
||||
def_or_undef (parse_in, "__tune_amdfam10__");
|
||||
break;
|
||||
case PROCESSOR_PENTIUM4:
|
||||
def_or_undef (parse_in, "__tune_pentium4__");
|
||||
break;
|
||||
case PROCESSOR_NOCONA:
|
||||
def_or_undef (parse_in, "__tune_nocona__");
|
||||
break;
|
||||
case PROCESSOR_CORE2:
|
||||
def_or_undef (parse_in, "__tune_core2__");
|
||||
break;
|
||||
case PROCESSOR_GENERIC32:
|
||||
case PROCESSOR_GENERIC64:
|
||||
break;
|
||||
/* use PROCESSOR_max to not set/unset the tune macro. */
|
||||
case PROCESSOR_max:
|
||||
break;
|
||||
}
|
||||
|
||||
if (isa_flag & OPTION_MASK_ISA_MMX)
|
||||
def_or_undef (parse_in, "__MMX__");
|
||||
if (isa_flag & OPTION_MASK_ISA_3DNOW)
|
||||
def_or_undef (parse_in, "__3dNOW__");
|
||||
if (isa_flag & OPTION_MASK_ISA_3DNOW_A)
|
||||
def_or_undef (parse_in, "__3dNOW_A__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE)
|
||||
def_or_undef (parse_in, "__SSE__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE2)
|
||||
def_or_undef (parse_in, "__SSE2__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE3)
|
||||
def_or_undef (parse_in, "__SSE3__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSSE3)
|
||||
def_or_undef (parse_in, "__SSSE3__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE4_1)
|
||||
def_or_undef (parse_in, "__SSE4_1__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE4_2)
|
||||
def_or_undef (parse_in, "__SSE4_2__");
|
||||
if (isa_flag & OPTION_MASK_ISA_AES)
|
||||
def_or_undef (parse_in, "__AES__");
|
||||
if (isa_flag & OPTION_MASK_ISA_PCLMUL)
|
||||
def_or_undef (parse_in, "__PCLMUL__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE4A)
|
||||
def_or_undef (parse_in, "__SSE4A__");
|
||||
if (isa_flag & OPTION_MASK_ISA_SSE5)
|
||||
def_or_undef (parse_in, "__SSE5__");
|
||||
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE))
|
||||
def_or_undef (parse_in, "__SSE_MATH__");
|
||||
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
|
||||
def_or_undef (parse_in, "__SSE2_MATH__");
|
||||
}
|
||||
|
||||
|
||||
/* Hook to validate the current #pragma option and set the state, and update
|
||||
the macros based on what was changed. */
|
||||
|
||||
static bool
|
||||
ix86_pragma_option_parse (tree args)
|
||||
{
|
||||
tree prev_tree = build_target_option_node ();
|
||||
tree cur_tree;
|
||||
struct cl_target_option *prev_opt;
|
||||
struct cl_target_option *cur_opt;
|
||||
int prev_isa;
|
||||
int cur_isa;
|
||||
int diff_isa;
|
||||
enum processor_type prev_arch;
|
||||
enum processor_type prev_tune;
|
||||
enum processor_type cur_arch;
|
||||
enum processor_type cur_tune;
|
||||
|
||||
if (! args)
|
||||
{
|
||||
cur_tree = target_option_default_node;
|
||||
cl_target_option_restore (TREE_TARGET_OPTION (cur_tree));
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_tree = ix86_valid_option_attribute_tree (args);
|
||||
if (!cur_tree)
|
||||
return false;
|
||||
}
|
||||
|
||||
target_option_current_node = cur_tree;
|
||||
|
||||
/* Figure out the previous/current isa, arch, tune and the differences. */
|
||||
prev_opt = TREE_TARGET_OPTION (prev_tree);
|
||||
cur_opt = TREE_TARGET_OPTION (cur_tree);
|
||||
prev_isa = prev_opt->ix86_isa_flags;
|
||||
cur_isa = cur_opt->ix86_isa_flags;
|
||||
diff_isa = (prev_isa ^ cur_isa);
|
||||
prev_arch = prev_opt->arch;
|
||||
prev_tune = prev_opt->tune;
|
||||
cur_arch = cur_opt->arch;
|
||||
cur_tune = cur_opt->tune;
|
||||
|
||||
/* If the same processor is used for both previous and current options, don't
|
||||
change the macros. */
|
||||
if (cur_arch == prev_arch)
|
||||
cur_arch = prev_arch = PROCESSOR_max;
|
||||
|
||||
if (cur_tune == prev_tune)
|
||||
cur_tune = prev_tune = PROCESSOR_max;
|
||||
|
||||
/* Undef all of the macros for that are no longer current. */
|
||||
ix86_target_macros_internal (prev_isa & diff_isa,
|
||||
prev_arch,
|
||||
prev_tune,
|
||||
prev_opt->fpmath,
|
||||
cpp_undef);
|
||||
|
||||
/* Define all of the macros for new options that were just turned on. */
|
||||
ix86_target_macros_internal (cur_isa & diff_isa,
|
||||
cur_arch,
|
||||
cur_tune,
|
||||
cur_opt->fpmath,
|
||||
cpp_define);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Function to tell the preprocessor about the defines for the current target. */
|
||||
|
||||
void
|
||||
ix86_target_macros (void)
|
||||
{
|
||||
/* 32/64-bit won't change with target specific options, so do the assert and
|
||||
builtin_define_std calls here. */
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
cpp_assert (parse_in, "cpu=x86_64");
|
||||
cpp_assert (parse_in, "machine=x86_64");
|
||||
cpp_define (parse_in, "__amd64");
|
||||
cpp_define (parse_in, "__amd64__");
|
||||
cpp_define (parse_in, "__x86_64");
|
||||
cpp_define (parse_in, "__x86_64__");
|
||||
}
|
||||
else
|
||||
{
|
||||
cpp_assert (parse_in, "cpu=i386");
|
||||
cpp_assert (parse_in, "machine=i386");
|
||||
builtin_define_std ("i386");
|
||||
}
|
||||
|
||||
ix86_target_macros_internal (ix86_isa_flags,
|
||||
ix86_arch,
|
||||
ix86_tune,
|
||||
ix86_fpmath,
|
||||
cpp_define);
|
||||
}
|
||||
|
||||
|
||||
/* Register target pragmas. We need to add the hook for parsing #pragma GCC
|
||||
option here rather than in i386.c since it will pull in various preprocessor
|
||||
functions, and those are not present in languages like fortran without a
|
||||
preprocessor. */
|
||||
|
||||
void
|
||||
ix86_register_pragmas (void)
|
||||
{
|
||||
/* Update pragma hook to allow parsing #pragma GCC option. */
|
||||
targetm.target_option.pragma_parse = ix86_pragma_option_parse;
|
||||
|
||||
#ifdef REGISTER_SUBTARGET_PRAGMAS
|
||||
REGISTER_SUBTARGET_PRAGMAS ();
|
||||
#endif
|
||||
}
|
|
@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Functions in i386.c */
|
||||
extern void override_options (void);
|
||||
extern void override_options (bool);
|
||||
extern void optimization_options (int, int);
|
||||
|
||||
extern int ix86_can_use_return_insn_p (void);
|
||||
|
@ -202,6 +202,7 @@ extern int ix86_constant_alignment (tree, int);
|
|||
extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
|
||||
extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
|
||||
extern int x86_field_alignment (tree, int);
|
||||
extern tree ix86_valid_option_attribute_tree (tree);
|
||||
#endif
|
||||
|
||||
extern rtx ix86_tls_get_addr (void);
|
||||
|
@ -215,6 +216,10 @@ extern void ix86_expand_reduc_v4sf (rtx (*)(rtx, rtx, rtx), rtx, rtx);
|
|||
extern bool ix86_sse5_valid_op_p (rtx [], rtx, int, bool, int, bool);
|
||||
extern void ix86_expand_sse5_multiple_memory (rtx [], int, enum machine_mode);
|
||||
|
||||
/* In i386-c.c */
|
||||
extern void ix86_target_macros (void);
|
||||
extern void ix86_register_pragmas (void);
|
||||
|
||||
/* In winnt.c */
|
||||
extern void i386_pe_unique_section (tree, int);
|
||||
extern void i386_pe_declare_function_type (FILE *, const char *, int);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -49,6 +49,13 @@ along with GCC; see the file COPYING3. If not see
|
|||
#define TARGET_SSE4A OPTION_ISA_SSE4A
|
||||
#define TARGET_SSE5 OPTION_ISA_SSE5
|
||||
#define TARGET_ROUND OPTION_ISA_ROUND
|
||||
#define TARGET_ABM OPTION_ISA_ABM
|
||||
#define TARGET_POPCNT OPTION_ISA_POPCNT
|
||||
#define TARGET_SAHF OPTION_ISA_SAHF
|
||||
#define TARGET_AES OPTION_ISA_AES
|
||||
#define TARGET_PCLMUL OPTION_ISA_PCLMUL
|
||||
#define TARGET_CMPXCHG16B OPTION_ISA_CX16
|
||||
|
||||
|
||||
/* SSE5 and SSE4.1 define the same round instructions */
|
||||
#define OPTION_MASK_ISA_ROUND (OPTION_MASK_ISA_SSE4_1 | OPTION_MASK_ISA_SSE5)
|
||||
|
@ -286,7 +293,7 @@ enum ix86_tune_indices {
|
|||
X86_TUNE_LAST
|
||||
};
|
||||
|
||||
extern unsigned int ix86_tune_features[X86_TUNE_LAST];
|
||||
extern unsigned char ix86_tune_features[X86_TUNE_LAST];
|
||||
|
||||
#define TARGET_USE_LEAVE ix86_tune_features[X86_TUNE_USE_LEAVE]
|
||||
#define TARGET_PUSH_MEMORY ix86_tune_features[X86_TUNE_PUSH_MEMORY]
|
||||
|
@ -380,7 +387,7 @@ enum ix86_arch_indices {
|
|||
X86_ARCH_LAST
|
||||
};
|
||||
|
||||
extern unsigned int ix86_arch_features[X86_ARCH_LAST];
|
||||
extern unsigned char ix86_arch_features[X86_ARCH_LAST];
|
||||
|
||||
#define TARGET_CMOVE ix86_arch_features[X86_ARCH_CMOVE]
|
||||
#define TARGET_CMPXCHG ix86_arch_features[X86_ARCH_CMPXCHG]
|
||||
|
@ -392,15 +399,7 @@ extern unsigned int ix86_arch_features[X86_ARCH_LAST];
|
|||
|
||||
extern int x86_prefetch_sse;
|
||||
|
||||
#define TARGET_ABM x86_abm
|
||||
#define TARGET_CMPXCHG16B x86_cmpxchg16b
|
||||
#define TARGET_POPCNT x86_popcnt
|
||||
#define TARGET_PREFETCH_SSE x86_prefetch_sse
|
||||
#define TARGET_SAHF x86_sahf
|
||||
#define TARGET_RECIP x86_recip
|
||||
#define TARGET_FUSED_MADD x86_fused_muladd
|
||||
#define TARGET_AES (TARGET_SSE2 && x86_aes)
|
||||
#define TARGET_PCLMUL (TARGET_SSE2 && x86_pclmul)
|
||||
|
||||
#define ASSEMBLER_DIALECT (ix86_asm_dialect)
|
||||
|
||||
|
@ -475,7 +474,7 @@ enum calling_abi
|
|||
Don't use this macro to turn on various extra optimizations for
|
||||
`-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
|
||||
|
||||
#define OVERRIDE_OPTIONS override_options ()
|
||||
#define OVERRIDE_OPTIONS override_options (true)
|
||||
|
||||
/* Define this to change the optimizations performed by default. */
|
||||
#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
|
||||
|
@ -537,196 +536,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|
|||
#endif
|
||||
|
||||
/* Target CPU builtins. */
|
||||
#define TARGET_CPU_CPP_BUILTINS() \
|
||||
do \
|
||||
{ \
|
||||
size_t arch_len = strlen (ix86_arch_string); \
|
||||
size_t tune_len = strlen (ix86_tune_string); \
|
||||
int last_arch_char = ix86_arch_string[arch_len - 1]; \
|
||||
int last_tune_char = ix86_tune_string[tune_len - 1]; \
|
||||
\
|
||||
if (TARGET_64BIT) \
|
||||
{ \
|
||||
builtin_assert ("cpu=x86_64"); \
|
||||
builtin_assert ("machine=x86_64"); \
|
||||
builtin_define ("__amd64"); \
|
||||
builtin_define ("__amd64__"); \
|
||||
builtin_define ("__x86_64"); \
|
||||
builtin_define ("__x86_64__"); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
builtin_assert ("cpu=i386"); \
|
||||
builtin_assert ("machine=i386"); \
|
||||
builtin_define_std ("i386"); \
|
||||
} \
|
||||
\
|
||||
/* Built-ins based on -march=. */ \
|
||||
switch (ix86_arch) \
|
||||
{ \
|
||||
case PROCESSOR_I386: \
|
||||
break; \
|
||||
case PROCESSOR_I486: \
|
||||
builtin_define ("__i486"); \
|
||||
builtin_define ("__i486__"); \
|
||||
break; \
|
||||
case PROCESSOR_PENTIUM: \
|
||||
builtin_define ("__i586"); \
|
||||
builtin_define ("__i586__"); \
|
||||
builtin_define ("__pentium"); \
|
||||
builtin_define ("__pentium__"); \
|
||||
if (last_arch_char == 'x') \
|
||||
builtin_define ("__pentium_mmx__"); \
|
||||
break; \
|
||||
case PROCESSOR_PENTIUMPRO: \
|
||||
builtin_define ("__i686"); \
|
||||
builtin_define ("__i686__"); \
|
||||
builtin_define ("__pentiumpro"); \
|
||||
builtin_define ("__pentiumpro__"); \
|
||||
break; \
|
||||
case PROCESSOR_GEODE: \
|
||||
builtin_define ("__geode"); \
|
||||
builtin_define ("__geode__"); \
|
||||
break; \
|
||||
case PROCESSOR_K6: \
|
||||
builtin_define ("__k6"); \
|
||||
builtin_define ("__k6__"); \
|
||||
if (last_arch_char == '2') \
|
||||
builtin_define ("__k6_2__"); \
|
||||
else if (last_arch_char == '3') \
|
||||
builtin_define ("__k6_3__"); \
|
||||
break; \
|
||||
case PROCESSOR_ATHLON: \
|
||||
builtin_define ("__athlon"); \
|
||||
builtin_define ("__athlon__"); \
|
||||
/* Only plain "athlon" lacks SSE. */ \
|
||||
if (last_arch_char != 'n') \
|
||||
builtin_define ("__athlon_sse__"); \
|
||||
break; \
|
||||
case PROCESSOR_K8: \
|
||||
builtin_define ("__k8"); \
|
||||
builtin_define ("__k8__"); \
|
||||
break; \
|
||||
case PROCESSOR_AMDFAM10: \
|
||||
builtin_define ("__amdfam10"); \
|
||||
builtin_define ("__amdfam10__"); \
|
||||
break; \
|
||||
case PROCESSOR_PENTIUM4: \
|
||||
builtin_define ("__pentium4"); \
|
||||
builtin_define ("__pentium4__"); \
|
||||
break; \
|
||||
case PROCESSOR_NOCONA: \
|
||||
builtin_define ("__nocona"); \
|
||||
builtin_define ("__nocona__"); \
|
||||
break; \
|
||||
case PROCESSOR_CORE2: \
|
||||
builtin_define ("__core2"); \
|
||||
builtin_define ("__core2__"); \
|
||||
break; \
|
||||
case PROCESSOR_GENERIC32: \
|
||||
case PROCESSOR_GENERIC64: \
|
||||
case PROCESSOR_max: \
|
||||
gcc_unreachable (); \
|
||||
} \
|
||||
\
|
||||
/* Built-ins based on -mtune=. */ \
|
||||
switch (ix86_tune) \
|
||||
{ \
|
||||
case PROCESSOR_I386: \
|
||||
builtin_define ("__tune_i386__"); \
|
||||
break; \
|
||||
case PROCESSOR_I486: \
|
||||
builtin_define ("__tune_i486__"); \
|
||||
break; \
|
||||
case PROCESSOR_PENTIUM: \
|
||||
builtin_define ("__tune_i586__"); \
|
||||
builtin_define ("__tune_pentium__"); \
|
||||
if (last_tune_char == 'x') \
|
||||
builtin_define ("__tune_pentium_mmx__"); \
|
||||
break; \
|
||||
case PROCESSOR_PENTIUMPRO: \
|
||||
builtin_define ("__tune_i686__"); \
|
||||
builtin_define ("__tune_pentiumpro__"); \
|
||||
switch (last_tune_char) \
|
||||
{ \
|
||||
case '3': \
|
||||
builtin_define ("__tune_pentium3__"); \
|
||||
/* FALLTHRU */ \
|
||||
case '2': \
|
||||
builtin_define ("__tune_pentium2__"); \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
case PROCESSOR_GEODE: \
|
||||
builtin_define ("__tune_geode__"); \
|
||||
break; \
|
||||
case PROCESSOR_K6: \
|
||||
builtin_define ("__tune_k6__"); \
|
||||
if (last_tune_char == '2') \
|
||||
builtin_define ("__tune_k6_2__"); \
|
||||
else if (last_tune_char == '3') \
|
||||
builtin_define ("__tune_k6_3__"); \
|
||||
break; \
|
||||
case PROCESSOR_ATHLON: \
|
||||
builtin_define ("__tune_athlon__"); \
|
||||
/* Only plain "athlon" lacks SSE. */ \
|
||||
if (last_tune_char != 'n') \
|
||||
builtin_define ("__tune_athlon_sse__"); \
|
||||
break; \
|
||||
case PROCESSOR_K8: \
|
||||
builtin_define ("__tune_k8__"); \
|
||||
break; \
|
||||
case PROCESSOR_AMDFAM10: \
|
||||
builtin_define ("__tune_amdfam10__"); \
|
||||
break; \
|
||||
case PROCESSOR_PENTIUM4: \
|
||||
builtin_define ("__tune_pentium4__"); \
|
||||
break; \
|
||||
case PROCESSOR_NOCONA: \
|
||||
builtin_define ("__tune_nocona__"); \
|
||||
break; \
|
||||
case PROCESSOR_CORE2: \
|
||||
builtin_define ("__tune_core2__"); \
|
||||
break; \
|
||||
case PROCESSOR_GENERIC32: \
|
||||
case PROCESSOR_GENERIC64: \
|
||||
break; \
|
||||
case PROCESSOR_max: \
|
||||
gcc_unreachable (); \
|
||||
} \
|
||||
\
|
||||
if (TARGET_MMX) \
|
||||
builtin_define ("__MMX__"); \
|
||||
if (TARGET_3DNOW) \
|
||||
builtin_define ("__3dNOW__"); \
|
||||
if (TARGET_3DNOW_A) \
|
||||
builtin_define ("__3dNOW_A__"); \
|
||||
if (TARGET_SSE) \
|
||||
builtin_define ("__SSE__"); \
|
||||
if (TARGET_SSE2) \
|
||||
builtin_define ("__SSE2__"); \
|
||||
if (TARGET_SSE3) \
|
||||
builtin_define ("__SSE3__"); \
|
||||
if (TARGET_SSSE3) \
|
||||
builtin_define ("__SSSE3__"); \
|
||||
if (TARGET_SSE4_1) \
|
||||
builtin_define ("__SSE4_1__"); \
|
||||
if (TARGET_SSE4_2) \
|
||||
builtin_define ("__SSE4_2__"); \
|
||||
if (TARGET_AES) \
|
||||
builtin_define ("__AES__"); \
|
||||
if (TARGET_PCLMUL) \
|
||||
builtin_define ("__PCLMUL__"); \
|
||||
if (TARGET_SSE4A) \
|
||||
builtin_define ("__SSE4A__"); \
|
||||
if (TARGET_SSE5) \
|
||||
builtin_define ("__SSE5__"); \
|
||||
if (TARGET_SSE_MATH && TARGET_SSE) \
|
||||
builtin_define ("__SSE_MATH__"); \
|
||||
if (TARGET_SSE_MATH && TARGET_SSE2) \
|
||||
builtin_define ("__SSE2_MATH__"); \
|
||||
} \
|
||||
while (0)
|
||||
#define TARGET_CPU_CPP_BUILTINS() ix86_target_macros ()
|
||||
|
||||
/* Target Pragmas. */
|
||||
#define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
|
||||
|
||||
enum target_cpu_default
|
||||
{
|
||||
|
|
|
@ -18,24 +18,58 @@
|
|||
; along with GCC; see the file COPYING3. If not see
|
||||
; <http://www.gnu.org/licenses/>.
|
||||
|
||||
;; Definitions to add to the cl_target_option structure
|
||||
;; -march= processor
|
||||
TargetSave
|
||||
unsigned char arch
|
||||
|
||||
;; -mtune= processor
|
||||
TargetSave
|
||||
unsigned char tune
|
||||
|
||||
;; -mfpath=
|
||||
TargetSave
|
||||
unsigned char fpmath
|
||||
|
||||
;; branch cost
|
||||
TargetSave
|
||||
unsigned char branch_cost
|
||||
|
||||
;; which flags were passed by the user
|
||||
TargetSave
|
||||
int ix86_isa_flags_explicit
|
||||
|
||||
;; which flags were passed by the user
|
||||
TargetSave
|
||||
int target_flags_explicit
|
||||
|
||||
;; whether -mtune was not specified
|
||||
TargetSave
|
||||
unsigned char tune_defaulted
|
||||
|
||||
;; whether -march was specified
|
||||
TargetSave
|
||||
unsigned char arch_specified
|
||||
|
||||
;; x86 options
|
||||
m128bit-long-double
|
||||
Target RejectNegative Report Mask(128BIT_LONG_DOUBLE)
|
||||
Target RejectNegative Report Mask(128BIT_LONG_DOUBLE) Save
|
||||
sizeof(long double) is 16
|
||||
|
||||
m80387
|
||||
Target Report Mask(80387)
|
||||
Target Report Mask(80387) Save
|
||||
Use hardware fp
|
||||
|
||||
m96bit-long-double
|
||||
Target RejectNegative Report InverseMask(128BIT_LONG_DOUBLE)
|
||||
Target RejectNegative Report InverseMask(128BIT_LONG_DOUBLE) Save
|
||||
sizeof(long double) is 12
|
||||
|
||||
maccumulate-outgoing-args
|
||||
Target Report Mask(ACCUMULATE_OUTGOING_ARGS)
|
||||
Target Report Mask(ACCUMULATE_OUTGOING_ARGS) Save
|
||||
Reserve space for outgoing arguments in the function prologue
|
||||
|
||||
malign-double
|
||||
Target Report Mask(ALIGN_DOUBLE)
|
||||
Target Report Mask(ALIGN_DOUBLE) Save
|
||||
Align some doubles on dword boundary
|
||||
|
||||
malign-functions=
|
||||
|
@ -51,7 +85,7 @@ Target RejectNegative Joined Var(ix86_align_loops_string)
|
|||
Loop code aligned to this power of 2
|
||||
|
||||
malign-stringops
|
||||
Target RejectNegative Report InverseMask(NO_ALIGN_STRINGOPS, ALIGN_STRINGOPS)
|
||||
Target RejectNegative Report InverseMask(NO_ALIGN_STRINGOPS, ALIGN_STRINGOPS) Save
|
||||
Align destination of the string operations
|
||||
|
||||
march=
|
||||
|
@ -75,11 +109,11 @@ Target RejectNegative Joined Var(ix86_cmodel_string)
|
|||
Use given x86-64 code model
|
||||
|
||||
mfancy-math-387
|
||||
Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387)
|
||||
Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save
|
||||
Generate sin, cos, sqrt for FPU
|
||||
|
||||
mfp-ret-in-387
|
||||
Target Report Mask(FLOAT_RETURNS)
|
||||
Target Report Mask(FLOAT_RETURNS) Save
|
||||
Return values of functions in FPU registers
|
||||
|
||||
mfpmath=
|
||||
|
@ -87,19 +121,19 @@ Target RejectNegative Joined Var(ix86_fpmath_string)
|
|||
Generate floating point mathematics using given instruction set
|
||||
|
||||
mhard-float
|
||||
Target RejectNegative Mask(80387) MaskExists
|
||||
Target RejectNegative Mask(80387) MaskExists Save
|
||||
Use hardware fp
|
||||
|
||||
mieee-fp
|
||||
Target Report Mask(IEEE_FP)
|
||||
Target Report Mask(IEEE_FP) Save
|
||||
Use IEEE math for fp comparisons
|
||||
|
||||
minline-all-stringops
|
||||
Target Report Mask(INLINE_ALL_STRINGOPS)
|
||||
Target Report Mask(INLINE_ALL_STRINGOPS) Save
|
||||
Inline all known string operations
|
||||
|
||||
minline-stringops-dynamically
|
||||
Target Report Mask(INLINE_STRINGOPS_DYNAMICALLY)
|
||||
Target Report Mask(INLINE_STRINGOPS_DYNAMICALLY) Save
|
||||
Inline memset/memcpy string operations, but perform inline version only for small blocks
|
||||
|
||||
mintel-syntax
|
||||
|
@ -107,23 +141,23 @@ Target Undocumented
|
|||
;; Deprecated
|
||||
|
||||
mms-bitfields
|
||||
Target Report Mask(MS_BITFIELD_LAYOUT)
|
||||
Target Report Mask(MS_BITFIELD_LAYOUT) Save
|
||||
Use native (MS) bitfield layout
|
||||
|
||||
mno-align-stringops
|
||||
Target RejectNegative Report Mask(NO_ALIGN_STRINGOPS) Undocumented
|
||||
Target RejectNegative Report Mask(NO_ALIGN_STRINGOPS) Undocumented Save
|
||||
|
||||
mno-fancy-math-387
|
||||
Target RejectNegative Report Mask(NO_FANCY_MATH_387) Undocumented
|
||||
Target RejectNegative Report Mask(NO_FANCY_MATH_387) Undocumented Save
|
||||
|
||||
mno-push-args
|
||||
Target RejectNegative Report Mask(NO_PUSH_ARGS) Undocumented
|
||||
Target RejectNegative Report Mask(NO_PUSH_ARGS) Undocumented Save
|
||||
|
||||
mno-red-zone
|
||||
Target RejectNegative Report Mask(NO_RED_ZONE) Undocumented
|
||||
Target RejectNegative Report Mask(NO_RED_ZONE) Undocumented Save
|
||||
|
||||
momit-leaf-frame-pointer
|
||||
Target Report Mask(OMIT_LEAF_FRAME_POINTER)
|
||||
Target Report Mask(OMIT_LEAF_FRAME_POINTER) Save
|
||||
Omit the frame pointer in leaf functions
|
||||
|
||||
mpc
|
||||
|
@ -135,11 +169,11 @@ Target RejectNegative Joined Var(ix86_preferred_stack_boundary_string)
|
|||
Attempt to keep stack aligned to this power of 2
|
||||
|
||||
mpush-args
|
||||
Target Report InverseMask(NO_PUSH_ARGS, PUSH_ARGS)
|
||||
Target Report InverseMask(NO_PUSH_ARGS, PUSH_ARGS) Save
|
||||
Use push instructions to save outgoing arguments
|
||||
|
||||
mred-zone
|
||||
Target RejectNegative Report InverseMask(NO_RED_ZONE, RED_ZONE)
|
||||
Target RejectNegative Report InverseMask(NO_RED_ZONE, RED_ZONE) Save
|
||||
Use red-zone in the x86-64 code
|
||||
|
||||
mregparm=
|
||||
|
@ -147,15 +181,15 @@ Target RejectNegative Joined Var(ix86_regparm_string)
|
|||
Number of registers used to pass integer arguments
|
||||
|
||||
mrtd
|
||||
Target Report Mask(RTD)
|
||||
Target Report Mask(RTD) Save
|
||||
Alternate calling convention
|
||||
|
||||
msoft-float
|
||||
Target InverseMask(80387)
|
||||
Target InverseMask(80387) Save
|
||||
Do not use hardware fp
|
||||
|
||||
msseregparm
|
||||
Target RejectNegative Mask(SSEREGPARM)
|
||||
Target RejectNegative Mask(SSEREGPARM) Save
|
||||
Use SSE register passing conventions for SF and DF mode
|
||||
|
||||
mstackrealign
|
||||
|
@ -163,7 +197,7 @@ Target Report Var(ix86_force_align_arg_pointer)
|
|||
Realign stack in prologue
|
||||
|
||||
mstack-arg-probe
|
||||
Target Report Mask(STACK_PROBE)
|
||||
Target Report Mask(STACK_PROBE) Save
|
||||
Enable stack probing
|
||||
|
||||
mstringop-strategy=
|
||||
|
@ -186,104 +220,105 @@ mveclibabi=
|
|||
Target RejectNegative Joined Var(ix86_veclibabi_string)
|
||||
Vector library ABI to use
|
||||
|
||||
;; ISA support
|
||||
|
||||
m32
|
||||
Target RejectNegative Negative(m64) Report InverseMask(ISA_64BIT) Var(ix86_isa_flags) VarExists
|
||||
Generate 32bit i386 code
|
||||
|
||||
m64
|
||||
Target RejectNegative Negative(m32) Report Mask(ISA_64BIT) Var(ix86_isa_flags) VarExists
|
||||
Generate 64bit x86-64 code
|
||||
|
||||
mmmx
|
||||
Target Report Mask(ISA_MMX) Var(ix86_isa_flags) VarExists
|
||||
Support MMX built-in functions
|
||||
|
||||
m3dnow
|
||||
Target Report Mask(ISA_3DNOW) Var(ix86_isa_flags) VarExists
|
||||
Support 3DNow! built-in functions
|
||||
|
||||
m3dnowa
|
||||
Target Undocumented Mask(ISA_3DNOW_A) Var(ix86_isa_flags) VarExists
|
||||
Support Athlon 3Dnow! built-in functions
|
||||
|
||||
msse
|
||||
Target Report Mask(ISA_SSE) Var(ix86_isa_flags) VarExists
|
||||
Support MMX and SSE built-in functions and code generation
|
||||
|
||||
msse2
|
||||
Target Report Mask(ISA_SSE2) Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE and SSE2 built-in functions and code generation
|
||||
|
||||
msse3
|
||||
Target Report Mask(ISA_SSE3) Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE, SSE2 and SSE3 built-in functions and code generation
|
||||
|
||||
mssse3
|
||||
Target Report Mask(ISA_SSSE3) Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE, SSE2, SSE3 and SSSE3 built-in functions and code generation
|
||||
|
||||
msse4.1
|
||||
Target Report Mask(ISA_SSE4_1) Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 built-in functions and code generation
|
||||
|
||||
msse4.2
|
||||
Target Report Mask(ISA_SSE4_2) Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation
|
||||
|
||||
msse4
|
||||
Target RejectNegative Report Mask(ISA_SSE4_2) MaskExists Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation
|
||||
|
||||
mno-sse4
|
||||
Target RejectNegative Report InverseMask(ISA_SSE4_1) MaskExists Var(ix86_isa_flags) VarExists
|
||||
Do not support SSE4.1 and SSE4.2 built-in functions and code generation
|
||||
|
||||
msse4a
|
||||
Target Report Mask(ISA_SSE4A) Var(ix86_isa_flags) VarExists
|
||||
Support MMX, SSE, SSE2, SSE3 and SSE4A built-in functions and code generation
|
||||
|
||||
msse5
|
||||
Target Report Mask(ISA_SSE5) Var(ix86_isa_flags) VarExists
|
||||
Support SSE5 built-in functions and code generation
|
||||
|
||||
;; Instruction support
|
||||
|
||||
mcld
|
||||
Target Report Mask(CLD)
|
||||
Generate cld instruction in the function prologue.
|
||||
|
||||
mabm
|
||||
Target Report RejectNegative Var(x86_abm)
|
||||
Support code generation of Advanced Bit Manipulation (ABM) instructions.
|
||||
|
||||
mcx16
|
||||
Target Report RejectNegative Var(x86_cmpxchg16b)
|
||||
Support code generation of cmpxchg16b instruction.
|
||||
|
||||
mpopcnt
|
||||
Target Report RejectNegative Var(x86_popcnt)
|
||||
Support code generation of popcnt instruction.
|
||||
|
||||
msahf
|
||||
Target Report RejectNegative Var(x86_sahf)
|
||||
Support code generation of sahf instruction in 64bit x86-64 code.
|
||||
|
||||
mrecip
|
||||
Target Report RejectNegative Var(x86_recip)
|
||||
Target Report Mask(RECIP) Save
|
||||
Generate reciprocals instead of divss and sqrtss.
|
||||
|
||||
mcld
|
||||
Target Report Mask(CLD) Save
|
||||
Generate cld instruction in the function prologue.
|
||||
|
||||
mno-fused-madd
|
||||
Target RejectNegative Report Mask(NO_FUSED_MADD) Undocumented Save
|
||||
|
||||
mfused-madd
|
||||
Target Report Var(x86_fused_muladd) Init(1)
|
||||
Target Report InverseMask(NO_FUSED_MADD, FUSED_MADD) Save
|
||||
Enable automatic generation of fused floating point multiply-add instructions
|
||||
if the ISA supports such instructions. The -mfused-madd option is on by
|
||||
default.
|
||||
|
||||
;; ISA support
|
||||
|
||||
m32
|
||||
Target RejectNegative Negative(m64) Report InverseMask(ISA_64BIT) Var(ix86_isa_flags) VarExists Save
|
||||
Generate 32bit i386 code
|
||||
|
||||
m64
|
||||
Target RejectNegative Negative(m32) Report Mask(ISA_64BIT) Var(ix86_isa_flags) VarExists Save
|
||||
Generate 64bit x86-64 code
|
||||
|
||||
mmmx
|
||||
Target Report Mask(ISA_MMX) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX built-in functions
|
||||
|
||||
m3dnow
|
||||
Target Report Mask(ISA_3DNOW) Var(ix86_isa_flags) VarExists Save
|
||||
Support 3DNow! built-in functions
|
||||
|
||||
m3dnowa
|
||||
Target Undocumented Mask(ISA_3DNOW_A) Var(ix86_isa_flags) VarExists Save
|
||||
Support Athlon 3Dnow! built-in functions
|
||||
|
||||
msse
|
||||
Target Report Mask(ISA_SSE) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX and SSE built-in functions and code generation
|
||||
|
||||
msse2
|
||||
Target Report Mask(ISA_SSE2) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE and SSE2 built-in functions and code generation
|
||||
|
||||
msse3
|
||||
Target Report Mask(ISA_SSE3) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE, SSE2 and SSE3 built-in functions and code generation
|
||||
|
||||
mssse3
|
||||
Target Report Mask(ISA_SSSE3) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE, SSE2, SSE3 and SSSE3 built-in functions and code generation
|
||||
|
||||
msse4.1
|
||||
Target Report Mask(ISA_SSE4_1) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 built-in functions and code generation
|
||||
|
||||
msse4.2
|
||||
Target Report Mask(ISA_SSE4_2) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation
|
||||
|
||||
msse4
|
||||
Target RejectNegative Report Mask(ISA_SSE4_2) MaskExists Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation
|
||||
|
||||
mno-sse4
|
||||
Target RejectNegative Report InverseMask(ISA_SSE4_1) MaskExists Var(ix86_isa_flags) VarExists Save
|
||||
Do not support SSE4.1 and SSE4.2 built-in functions and code generation
|
||||
|
||||
msse4a
|
||||
Target Report Mask(ISA_SSE4A) Var(ix86_isa_flags) VarExists Save
|
||||
Support MMX, SSE, SSE2, SSE3 and SSE4A built-in functions and code generation
|
||||
|
||||
msse5
|
||||
Target Report Mask(ISA_SSE5) Var(ix86_isa_flags) VarExists Save
|
||||
Support SSE5 built-in functions and code generation
|
||||
|
||||
mabm
|
||||
Target Report Mask(ISA_ABM) Var(ix86_isa_flags) VarExists Save
|
||||
Support code generation of Advanced Bit Manipulation (ABM) instructions.
|
||||
|
||||
mpopcnt
|
||||
Target Report Mask(ISA_POPCNT) Var(ix86_isa_flags) VarExists Save
|
||||
Support code generation of popcnt instruction.
|
||||
|
||||
mcx16
|
||||
Target Report Mask(ISA_CX16) Var(ix86_isa_flags) VarExists Save
|
||||
Support code generation of cmpxchg16b instruction.
|
||||
|
||||
msahf
|
||||
Target Report Mask(ISA_SAHF) Var(ix86_isa_flags) VarExists Save
|
||||
Support code generation of sahf instruction in 64bit x86-64 code.
|
||||
|
||||
maes
|
||||
Target Report RejectNegative Var(x86_aes)
|
||||
Target Report Mask(ISA_AES) Var(ix86_isa_flags) VarExists Save
|
||||
Support AES built-in functions and code generation
|
||||
|
||||
mpclmul
|
||||
Target Report RejectNegative Var(x86_pclmul)
|
||||
Target Report Mask(ISA_PCLMUL) Var(ix86_isa_flags) VarExists Save
|
||||
Support PCLMUL built-in functions and code generation
|
||||
|
|
13
gcc/config/i386/t-i386
Normal file
13
gcc/config/i386/t-i386
Normal file
|
@ -0,0 +1,13 @@
|
|||
i386.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(TREE_H) $(TM_P_H) $(REGS_H) hard-reg-set.h \
|
||||
$(REAL_H) insn-config.h conditions.h output.h insn-codes.h \
|
||||
$(INSN_ATTR_H) $(FLAGS_H) $(C_COMMON_H) except.h $(FUNCTION_H) \
|
||||
$(RECOG_H) $(EXPR_H) $(OPTABS_H) toplev.h $(BASIC_BLOCK_H) \
|
||||
$(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \
|
||||
$(TREE_GIMPLE_H) dwarf2.h $(DF_H) tm-constrs.h $(PARAMS_H)
|
||||
|
||||
i386-c.o: $(srcdir)/config/i386/i386-c.c \
|
||||
$(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(FLAGS_H) $(C_COMMON_H) $(GGC_H) \
|
||||
$(TARGET_H) $(TARGET_DEF_H) $(CPPLIB_H) $(C_PRAGMA_H)
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/i386-c.c
|
|
@ -50,6 +50,8 @@ typedef union tree_node *tree;
|
|||
typedef const union tree_node *const_tree;
|
||||
union section;
|
||||
typedef union section section;
|
||||
struct cl_target_option;
|
||||
struct cl_optimization;
|
||||
|
||||
/* The major intermediate representations of GCC. */
|
||||
enum ir_type {
|
||||
|
|
|
@ -1330,6 +1330,8 @@ a containing function, and the back end must take appropriate action.
|
|||
@findex DECL_GLOBAL_CTOR_P
|
||||
@findex DECL_GLOBAL_DTOR_P
|
||||
@findex GLOBAL_INIT_PRIORITY
|
||||
@findex DECL_FUNCTION_SPECIFIC_TARGET
|
||||
@findex DECL_FUNCTION_SPECIFIC_OPTIMIZATION
|
||||
|
||||
The following macros and functions can be used on a @code{FUNCTION_DECL}:
|
||||
@ftable @code
|
||||
|
@ -1514,6 +1516,17 @@ is of the form `@code{()}'.
|
|||
This predicate holds if the function an overloaded
|
||||
@code{operator delete[]}.
|
||||
|
||||
@item DECL_FUNCTION_SPECIFIC_TARGET
|
||||
This macro returns a tree node that holds the target options that are
|
||||
to be used to compile this particular function or @code{NULL_TREE} if
|
||||
the function is to be compiled with the target options specified on
|
||||
the command line.
|
||||
|
||||
@item DECL_FUNCTION_SPECIFIC_OPTIMIZATION
|
||||
This macro returns a tree node that holds the optimization options
|
||||
that are to be used to compile this particular function or
|
||||
@code{NULL_TREE} if the function is to be compiled with the
|
||||
optimization options specified on the command line.
|
||||
@end ftable
|
||||
|
||||
@c ---------------------------------------------------------------------
|
||||
|
|
|
@ -1792,6 +1792,8 @@ the enclosing block.
|
|||
@cindex functions that are passed arguments in registers on the 386
|
||||
@cindex functions that pop the argument stack on the 386
|
||||
@cindex functions that do not pop the argument stack on the 386
|
||||
@cindex functions that have different compilation options on the 386
|
||||
@cindex functions that have different optimization options
|
||||
|
||||
In GNU C, you declare certain things about functions called in your program
|
||||
which help the compiler optimize function calls and check your code more
|
||||
|
@ -2662,6 +2664,207 @@ with the notable exceptions of @code{qsort} and @code{bsearch} that
|
|||
take function pointer arguments. The @code{nothrow} attribute is not
|
||||
implemented in GCC versions earlier than 3.3.
|
||||
|
||||
@item option
|
||||
@cindex @code{option} function attribute
|
||||
The @code{option} attribute is used to specify that a function is to
|
||||
be compiled with different target options than specified on the
|
||||
command line. This can be used for instance to have functions
|
||||
compiled with a different ISA (instruction set architecture) than the
|
||||
default. You can also use the @samp{#pragma GCC option} pragma to set
|
||||
more than one function to be compiled with specific target options.
|
||||
@xref{Function Specific Option Pragmas}, for details about the
|
||||
@samp{#pragma GCC option} pragma.
|
||||
|
||||
For instance on a 386, you could compile one function with
|
||||
@code{option("sse4.1,arch=core2")} and another with
|
||||
@code{option("sse4a,arch=amdfam10")} that would be equivalent to
|
||||
compiling the first function with @option{-msse4.1} and
|
||||
@option{-march=core2} options, and the second function with
|
||||
@option{-msse4a} and @option{-march=amdfam10} options. It is up to the
|
||||
user to make sure that a function is only invoked on a machine that
|
||||
supports the particular ISA it was compiled for (for example by using
|
||||
@code{cpuid} on 386 to determine what feature bits and architecture
|
||||
family are used).
|
||||
|
||||
@smallexample
|
||||
int core2_func (void) __attribute__ ((__option__ ("arch=core2")));
|
||||
int sse3_func (void) __attribute__ ((__option__ ("sse3")));
|
||||
@end smallexample
|
||||
|
||||
On the 386, the following options are allowed:
|
||||
|
||||
@table @samp
|
||||
@item abm
|
||||
@itemx no-abm
|
||||
@cindex option("abm")
|
||||
Enable/disable the generation of the advanced bit instructions.
|
||||
|
||||
@item aes
|
||||
@itemx no-aes
|
||||
@cindex @code{option("aes")} attribute
|
||||
Enable/disable the generation of the AES instructions.
|
||||
|
||||
@item mmx
|
||||
@itemx no-mmx
|
||||
@cindex @code{option("mmx")} attribute
|
||||
Enable/disable the generation of the MMX instructions.
|
||||
|
||||
@item pclmul
|
||||
@itemx no-pclmul
|
||||
@cindex @code{option("pclmul")} attribute
|
||||
Enable/disable the generation of the PCLMUL instructions.
|
||||
|
||||
@item popcnt
|
||||
@itemx no-popcnt
|
||||
@cindex @code{option("popcnt")} attribute
|
||||
Enable/disable the generation of the POPCNT instruction.
|
||||
|
||||
@item sse
|
||||
@itemx no-sse
|
||||
@cindex @code{option("sse")} attribute
|
||||
Enable/disable the generation of the SSE instructions.
|
||||
|
||||
@item sse2
|
||||
@itemx no-sse2
|
||||
@cindex @code{option("sse2")} attribute
|
||||
Enable/disable the generation of the SSE2 instructions.
|
||||
|
||||
@item sse3
|
||||
@itemx no-sse3
|
||||
@cindex @code{option("sse3")} attribute
|
||||
Enable/disable the generation of the SSE3 instructions.
|
||||
|
||||
@item sse4
|
||||
@itemx no-sse4
|
||||
@cindex @code{option("sse4")} attribute
|
||||
Enable/disable the generation of the SSE4 instructions (both SSE4.1
|
||||
and SSE4.2).
|
||||
|
||||
@item sse4.1
|
||||
@itemx no-sse4.1
|
||||
@cindex @code{option("sse4.1")} attribute
|
||||
Enable/disable the generation of the sse4.1 instructions.
|
||||
|
||||
@item sse4.2
|
||||
@itemx no-sse4.2
|
||||
@cindex @code{option("sse4.2")} attribute
|
||||
Enable/disable the generation of the sse4.2 instructions.
|
||||
|
||||
@item sse4a
|
||||
@itemx no-sse4a
|
||||
@cindex @code{option("sse4a")} attribute
|
||||
Enable/disable the generation of the SSE4A instructions.
|
||||
|
||||
@item sse5
|
||||
@itemx no-sse5
|
||||
@cindex @code{option("sse5")} attribute
|
||||
Enable/disable the generation of the SSE5 instructions.
|
||||
|
||||
@item ssse3
|
||||
@itemx no-ssse3
|
||||
@cindex @code{option("ssse3")} attribute
|
||||
Enable/disable the generation of the SSSE3 instructions.
|
||||
|
||||
@item cld
|
||||
@itemx no-cld
|
||||
@cindex @code{option("cld")} attribute
|
||||
Enable/disable the generation of the CLD before string moves.
|
||||
|
||||
@item fancy-math-387
|
||||
@itemx no-fancy-math-387
|
||||
@cindex @code{option("fancy-math-387")} attribute
|
||||
Enable/disable the generation of the @code{sin}, @code{cos}, and
|
||||
@code{sqrt} instructions on the 387 floating point unit.
|
||||
|
||||
@item fused-madd
|
||||
@itemx no-fused-madd
|
||||
@cindex @code{option("fused-madd")} attribute
|
||||
Enable/disable the generation of the fused multiply/add instructions.
|
||||
|
||||
@item ieee-fp
|
||||
@itemx no-ieee-fp
|
||||
@cindex @code{option("ieee-fp")} attribute
|
||||
Enable/disable the generation of floating point that depends on IEEE arithmetic.
|
||||
|
||||
@item inline-all-stringops
|
||||
@itemx no-inline-all-stringops
|
||||
@cindex @code{option("inline-all-stringops")} attribute
|
||||
Enable/disable inlining of string operations.
|
||||
|
||||
@item inline-stringops-dynamically
|
||||
@itemx no-inline-stringops-dynamically
|
||||
@cindex @code{option("inline-stringops-dynamically")} attribute
|
||||
Enable/disable the generation of the inline code to do small string
|
||||
operations and calling the library routines for large operations.
|
||||
|
||||
@item align-stringops
|
||||
@itemx no-align-stringops
|
||||
@cindex @code{option("align-stringops")} attribute
|
||||
Do/do not align destination of inlined string operations.
|
||||
|
||||
@item recip
|
||||
@itemx no-recip
|
||||
@cindex @code{option("recip")} attribute
|
||||
Enable/disable the generation of RCPSS, RCPPS, RSQRTSS and RSQRTPS
|
||||
instructions followed an additional Newton-Rhapson step instead of
|
||||
doing a floating point division.
|
||||
|
||||
@item arch=@var{ARCH}
|
||||
@cindex @code{option("arch=@var{ARCH}")} attribute
|
||||
Specify the architecture to generate code for in compiling the function.
|
||||
|
||||
@item tune=@var{TUNE}
|
||||
@cindex @code{option("tune=@var{TUNE}")} attribute
|
||||
Specify the architecture to tune for in compiling the function.
|
||||
|
||||
@item fpmath=@var{FPMATH}
|
||||
@cindex @code{option("fpmath=@var{FPMATH}")} attribute
|
||||
Specify which floating point unit to use. The
|
||||
@code{option("fpmath=sse,387")} option must be specified as
|
||||
@code{option("fpmath=sse+387")} because the comma would separate
|
||||
different options.
|
||||
@end table
|
||||
|
||||
On the 386, you can use either multiple strings to specify multiple
|
||||
options, or you can separate the option with a comma (@code{,}).
|
||||
|
||||
On the 386, the inliner will not inline a function that has different
|
||||
target options than the caller, unless the callee has a subset of the
|
||||
target options of the caller. For example a function declared with
|
||||
@code{option("sse5")} can inline a function with
|
||||
@code{option("sse2")}, since @code{-msse5} implies @code{-msse2}.
|
||||
|
||||
The @code{option} attribute is not implemented in GCC versions earlier
|
||||
than 4.4, and at present only the 386 uses it.
|
||||
|
||||
@item optimize
|
||||
@cindex @code{optimize} function attribute
|
||||
The @code{optimize} attribute is used to specify that a function is to
|
||||
be compiled with different optimization options than specified on the
|
||||
command line. Arguments can either be numbers or strings. Numbers
|
||||
are assumed to be an optimization level. Strings that begin with
|
||||
@code{O} are assumed to be an optimization option, while other options
|
||||
are assumed to be used with a @code{-f} prefix. You can also use the
|
||||
@samp{#pragma GCC optimize} pragma to set the optimization options
|
||||
that affect more than one function.
|
||||
@xref{Function Specific Option Pragmas}, for details about the
|
||||
@samp{#pragma GCC option} pragma.
|
||||
|
||||
This can be used for instance to have frequently executed functions
|
||||
compiled with more aggressive optimization options that produce faster
|
||||
and larger code, while other functions can be called with less
|
||||
aggressive options. The @code{hot} attribute implies
|
||||
@code{optimize("O3")}, and @code{cold} attribute implies
|
||||
@code{optimize("Os")}.
|
||||
|
||||
@smallexample
|
||||
int fast_func (void) __attribute__ ((__optimize__ ("O3,unroll-loops")));
|
||||
int slow_func (void) __attribute__ ((__optimize__ ("Os")));
|
||||
@end smallexample
|
||||
|
||||
The inliner will not inline functions with a higher optimization level
|
||||
than the caller or different space/time trade offs.
|
||||
|
||||
@item pure
|
||||
@cindex @code{pure} function attribute
|
||||
Many functions have no effects except the return value and their
|
||||
|
@ -2697,7 +2900,11 @@ all hot functions appears close together improving locality.
|
|||
When profile feedback is available, via @option{-fprofile-use}, hot functions
|
||||
are automatically detected and this attribute is ignored.
|
||||
|
||||
The @code{hot} attribute is not implemented in GCC versions earlier than 4.3.
|
||||
The @code{hot} attribute is not implemented in GCC versions earlier
|
||||
than 4.3.
|
||||
|
||||
Starting with GCC 4.4, the @code{hot} attribute sets
|
||||
@code{optimize("O3")} to turn on more aggressive optimization.
|
||||
|
||||
@item cold
|
||||
@cindex @code{cold} function attribute
|
||||
|
@ -2714,7 +2921,10 @@ occasions.
|
|||
When profile feedback is available, via @option{-fprofile-use}, hot functions
|
||||
are automatically detected and this attribute is ignored.
|
||||
|
||||
The @code{hot} attribute is not implemented in GCC versions earlier than 4.3.
|
||||
The @code{cold} attribute is not implemented in GCC versions earlier than 4.3.
|
||||
|
||||
Starting with GCC 4.4, the @code{cold} attribute sets
|
||||
@code{optimize("Os")} to save space.
|
||||
|
||||
@item regparm (@var{number})
|
||||
@cindex @code{regparm} attribute
|
||||
|
@ -11108,6 +11318,7 @@ for further explanation.
|
|||
* Diagnostic Pragmas::
|
||||
* Visibility Pragmas::
|
||||
* Push/Pop Macro Pragmas::
|
||||
* Function Specific Option Pragmas::
|
||||
@end menu
|
||||
|
||||
@node ARM Pragmas
|
||||
|
@ -11458,6 +11669,80 @@ int x [X];
|
|||
In this example, the definition of X as 1 is saved by @code{#pragma
|
||||
push_macro} and restored by @code{#pragma pop_macro}.
|
||||
|
||||
@node Function Specific Option Pragmas
|
||||
@subsection Function Specific Option Pragmas
|
||||
|
||||
@table @code
|
||||
@item #pragma GCC option (@var{"string"}...)
|
||||
@cindex pragma GCC option
|
||||
|
||||
This pragma allows you to set target specific options for functions
|
||||
defined later in the source file. One or more strings can be
|
||||
specified. Each function that is defined after this point will be as
|
||||
if @code{attribute((option("STRING")))} was specified for that
|
||||
function. The parenthesis around the options is optional.
|
||||
@xref{Function Attributes}, for more information about the
|
||||
@code{option} attribute and the attribute syntax.
|
||||
|
||||
The @samp{#pragma GCC option} pragma is not implemented in GCC
|
||||
versions earlier than 4.4, and is currently only implemented for the
|
||||
386 and x86_64 backend.
|
||||
@end table
|
||||
|
||||
@table @code
|
||||
@item #pragma GCC option (push)
|
||||
@itemx #pragma GCC option (pop)
|
||||
@cindex pragma GCC option
|
||||
|
||||
These pragmas maintain a stack of the current options. It is
|
||||
intended for include files where you temporarily want to switch to
|
||||
using a different @samp{#pragma GCC option} and then to pop back to
|
||||
the previous options.
|
||||
@end table
|
||||
|
||||
@table @code
|
||||
@item #pragma GCC option (reset)
|
||||
@cindex pragma, target option
|
||||
@cindex pragma GCC option
|
||||
|
||||
This pragma clears the current @code{#pragma GCC options} to use the
|
||||
default switches as specified on the command line.
|
||||
@end table
|
||||
@table @code
|
||||
@item #pragma GCC optimize (@var{"string"}...)
|
||||
@cindex pragma GCC optimize
|
||||
|
||||
This pragma allows you to set global optimization options for functions
|
||||
defined later in the source file. One or more strings can be
|
||||
specified. Each function that is defined after this point will be as
|
||||
if @code{attribute((optimize("STRING")))} was specified for that
|
||||
function. The parenthesis around the options is optional.
|
||||
@xref{Function Attributes}, for more information about the
|
||||
@code{optimize} attribute and the attribute syntax.
|
||||
|
||||
The @samp{#pragma GCC optimize} pragma is not implemented in GCC
|
||||
versions earlier than 4.4.
|
||||
@end table
|
||||
|
||||
@table @code
|
||||
@item #pragma GCC optimize (push)
|
||||
@itemx #pragma GCC optimize (pop)
|
||||
@cindex pragma GCC optimize
|
||||
|
||||
These pragmas maintain a stack of the current optimization options.
|
||||
It is intended for include files where you temporarily want to switch
|
||||
to using a different @code{#pragma GCC optimize} and then to pop back
|
||||
to the previous optimizations.
|
||||
@end table
|
||||
|
||||
@table @code
|
||||
@item #pragma GCC optimize reset
|
||||
@cindex pragma GCC optimize
|
||||
|
||||
This pragma clears the current @code{#pragma GCC optimize} to use the
|
||||
default switches as specified on the command line.
|
||||
@end table
|
||||
|
||||
@node Unnamed Fields
|
||||
@section Unnamed struct/union fields within structs/unions
|
||||
@cindex struct
|
||||
|
|
|
@ -10543,6 +10543,8 @@ code that expects temporaries to be 80bit.
|
|||
This is the default choice for the x86-64 compiler.
|
||||
|
||||
@item sse,387
|
||||
@itemx sse+387
|
||||
@itemx both
|
||||
Attempt to utilize both instruction sets at once. This effectively double the
|
||||
amount of available registers and on chips with separate execution units for
|
||||
387 and SSE the execution resources too. Use this option with care, as it is
|
||||
|
|
|
@ -35,8 +35,11 @@ has been declared in this way, it can be used as an option property.
|
|||
@xref{Option properties}.
|
||||
|
||||
@item
|
||||
An option definition record. These records have the following fields:
|
||||
A target specific save record to save additional information. These
|
||||
records have two fields: the string @samp{TargetSave}, and a
|
||||
declaration type to go in the @code{cl_target_option} structure.
|
||||
|
||||
@item
|
||||
@enumerate
|
||||
@item
|
||||
the name of the option, with the leading ``-'' removed
|
||||
|
@ -124,7 +127,10 @@ This property cannot be used alongside @code{Joined} or @code{Separate}.
|
|||
@item UInteger
|
||||
The option's argument is a non-negative integer. The option parser
|
||||
will check and convert the argument before passing it to the relevant
|
||||
option handler.
|
||||
option handler. @code{UInteger} should also be used on options like
|
||||
@code{-falign-loops} where both @code{-falign-loops} and
|
||||
@code{-falign-loops}=@var{n} are supported to make sure the saved
|
||||
options are given a full integer.
|
||||
|
||||
@item Var(@var{var})
|
||||
The state of this option should be stored in variable @var{var}.
|
||||
|
@ -221,4 +227,9 @@ The option should only be accepted if preprocessor condition
|
|||
option will be present even if @var{cond} is false; @var{cond} simply
|
||||
controls whether the option is accepted and whether it is printed in
|
||||
the @option{--help} output.
|
||||
|
||||
@item Save
|
||||
Build the @code{cl_target_option} structure to hold a copy of the
|
||||
option, add the functions @code{cl_target_option_save} and
|
||||
@code{cl_target_option_restore} to save and restore the options.
|
||||
@end table
|
||||
|
|
|
@ -9271,6 +9271,51 @@ attributes, @code{false} otherwise. By default, if a function has a
|
|||
target specific attribute attached to it, it will not be inlined.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_VALID_OPTION_ATTRIBUTE_P (tree @var{fndecl}, tree @var{name}, tree @var{args}, int @var{flags})
|
||||
This hook is called to parse the @code{attribute(option("..."))}, and
|
||||
it allows the function to set different target machine compile time
|
||||
options for the current function that might be different than the
|
||||
options specified on the command line. The hook should return
|
||||
@code{true} if the options are valid.
|
||||
|
||||
The hook should set the @var{DECL_FUNCTION_SPECIFIC_TARGET} field in
|
||||
the function declaration to hold a pointer to a target specific
|
||||
@var{struct cl_target_option} structure.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr})
|
||||
This hook is called to save any additional target specific information
|
||||
in the @var{struct cl_target_option} structure for function specific
|
||||
options.
|
||||
@xref{Option file format}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_OPTION_RESTORE (struct cl_target_option *@var{ptr})
|
||||
This hook is called to restore any additional target specific
|
||||
information in the @var{struct cl_target_option} structure for
|
||||
function specific options.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_OPTION_PRINT (struct cl_target_option *@var{ptr})
|
||||
This hook is called to print any additional target specific
|
||||
information in the @var{struct cl_target_option} structure for
|
||||
function specific options.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_OPTION_PRAGMA_PARSE (target @var{args})
|
||||
This target hook parses the options for @code{#pragma GCC option} to
|
||||
set the machine specific options for functions that occur later in the
|
||||
input stream. The options should be the same as handled by the
|
||||
@code{TARGET_VALID_OPTION_ATTRIBUTE_P} hook.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_CAN_INLINE_P (tree @var{caller}, tree @var{callee})
|
||||
This target hook returns @code{false} if the @var{caller} function
|
||||
cannot inline @var{callee}, based on target specific information. By
|
||||
default, inlining is not allowed if the callee function has function
|
||||
specific target options and the caller does not use the same options.
|
||||
@end deftypefn
|
||||
|
||||
@node Emulated TLS
|
||||
@section Emulating TLS
|
||||
@cindex Emulated TLS
|
||||
|
|
|
@ -3731,13 +3731,30 @@ debug_find_var_in_block_tree (tree var, tree block)
|
|||
|
||||
static bool in_dummy_function;
|
||||
|
||||
/* Invoke the target hook when setting cfun. */
|
||||
/* Invoke the target hook when setting cfun. Update the optimization options
|
||||
if the function uses different options than the default. */
|
||||
|
||||
static void
|
||||
invoke_set_current_function_hook (tree fndecl)
|
||||
{
|
||||
if (!in_dummy_function)
|
||||
targetm.set_current_function (fndecl);
|
||||
{
|
||||
tree opts = ((fndecl)
|
||||
? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl)
|
||||
: optimization_default_node);
|
||||
|
||||
if (!opts)
|
||||
opts = optimization_default_node;
|
||||
|
||||
/* Change optimization options if needed. */
|
||||
if (optimization_current_node != opts)
|
||||
{
|
||||
optimization_current_node = opts;
|
||||
cl_optimization_restore (TREE_OPTIMIZATION (opts));
|
||||
}
|
||||
|
||||
targetm.set_current_function (fndecl);
|
||||
}
|
||||
}
|
||||
|
||||
/* cfun should never be set directly; use this function. */
|
||||
|
|
|
@ -954,6 +954,14 @@ cgraph_decide_inlining_of_small_functions (void)
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (!tree_can_inline_p (edge->caller->decl, edge->callee->decl))
|
||||
{
|
||||
CALL_STMT_CANNOT_INLINE_P (edge->call_stmt) = true;
|
||||
edge->inline_failed = N_("target specific option mismatch");
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " inline_failed:%s.\n", edge->inline_failed);
|
||||
continue;
|
||||
}
|
||||
if (cgraph_recursive_inlining_p (edge->caller, edge->callee,
|
||||
&edge->inline_failed))
|
||||
{
|
||||
|
@ -1098,6 +1106,11 @@ cgraph_decide_inlining (void)
|
|||
if (cgraph_recursive_inlining_p (e->caller, e->callee,
|
||||
&e->inline_failed))
|
||||
continue;
|
||||
if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
|
||||
{
|
||||
CALL_STMT_CANNOT_INLINE_P (e->call_stmt) = true;
|
||||
continue;
|
||||
}
|
||||
cgraph_mark_inline_edge (e, true);
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
|
@ -1322,6 +1335,17 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (!tree_can_inline_p (node->decl, e->callee->decl))
|
||||
{
|
||||
CALL_STMT_CANNOT_INLINE_P (e->call_stmt) = true;
|
||||
if (dump_file)
|
||||
{
|
||||
indent_to (dump_file, depth);
|
||||
fprintf (dump_file,
|
||||
"Not inlining: Target specific option mismatch.\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
|
||||
!= gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl)))
|
||||
{
|
||||
|
@ -1418,6 +1442,17 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (!tree_can_inline_p (node->decl, e->callee->decl))
|
||||
{
|
||||
CALL_STMT_CANNOT_INLINE_P (e->call_stmt) = true;
|
||||
if (dump_file)
|
||||
{
|
||||
indent_to (dump_file, depth);
|
||||
fprintf (dump_file,
|
||||
"Not inlining: Target specific option mismatch.\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (cgraph_default_inline_p (e->callee, &failed_reason))
|
||||
inlined |= try_inline (e, mode, depth);
|
||||
else if (!flag_unit_at_a_time)
|
||||
|
|
|
@ -128,6 +128,23 @@ function var_type(flags)
|
|||
return "const char *"
|
||||
}
|
||||
|
||||
# Return the type of variable that should be associated with the given flags
|
||||
# for use within a structure. Simple variables are changed to unsigned char
|
||||
# type instead of int to save space.
|
||||
function var_type_struct(flags)
|
||||
{
|
||||
if (flag_set_p("UInteger", flags))
|
||||
return "int "
|
||||
else if (!flag_set_p("Joined.*", flags)) {
|
||||
if (flag_set_p(".*Mask.*", flags))
|
||||
return "int "
|
||||
else
|
||||
return "unsigned char "
|
||||
}
|
||||
else
|
||||
return "const char *"
|
||||
}
|
||||
|
||||
# Given that an option has flags FLAGS, return an initializer for the
|
||||
# "var_cond" and "var_value" fields of its cl_options[] entry.
|
||||
function var_set(flags)
|
||||
|
|
319
gcc/optc-gen.awk
319
gcc/optc-gen.awk
|
@ -28,6 +28,7 @@
|
|||
BEGIN {
|
||||
n_opts = 0
|
||||
n_langs = 0
|
||||
n_target_save = 0
|
||||
quote = "\042"
|
||||
comma = ","
|
||||
FS=SUBSEP
|
||||
|
@ -41,6 +42,11 @@ BEGIN {
|
|||
langs[n_langs] = $2
|
||||
n_langs++;
|
||||
}
|
||||
else if ($1 == "TargetSave") {
|
||||
# Make sure the declarations are put in source order
|
||||
target_save_decl[n_target_save] = $2
|
||||
n_target_save++
|
||||
}
|
||||
else {
|
||||
name = opt_args("Mask", $1)
|
||||
if (name == "") {
|
||||
|
@ -64,10 +70,17 @@ print "#include " quote "intl.h" quote
|
|||
print ""
|
||||
print "#ifdef GCC_DRIVER"
|
||||
print "int target_flags;"
|
||||
print "#else"
|
||||
print "#include " quote "flags.h" quote
|
||||
print "#include " quote "target.h" quote
|
||||
print "#endif /* GCC_DRIVER */"
|
||||
print ""
|
||||
|
||||
have_save = 0;
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
if (flag_set_p("Save", flags[i]))
|
||||
have_save = 1;
|
||||
|
||||
name = var_name(flags[i]);
|
||||
if (name == "")
|
||||
continue;
|
||||
|
@ -210,4 +223,310 @@ for (i = 0; i < n_opts; i++) {
|
|||
}
|
||||
|
||||
print "};"
|
||||
|
||||
print "";
|
||||
print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2)"
|
||||
print "";
|
||||
print "/* Save optimization variables into a structure. */"
|
||||
print "void";
|
||||
print "cl_optimization_save (struct cl_optimization *ptr)";
|
||||
print "{";
|
||||
|
||||
n_opt_char = 2;
|
||||
n_opt_short = 0;
|
||||
n_opt_int = 0;
|
||||
n_opt_other = 0;
|
||||
var_opt_char[0] = "optimize";
|
||||
var_opt_char[1] = "optimize_size";
|
||||
var_opt_range["optimize"] = "0, 255";
|
||||
var_opt_range["optimize_size"] = "0, 255";
|
||||
|
||||
# Sort by size to mimic how the structure is laid out to be friendlier to the
|
||||
# cache.
|
||||
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
if (flag_set_p("Optimization", flags[i])) {
|
||||
name = var_name(flags[i])
|
||||
if(name == "")
|
||||
continue;
|
||||
|
||||
if(name in var_opt_seen)
|
||||
continue;
|
||||
|
||||
var_opt_seen[name]++;
|
||||
otype = var_type_struct(flags[i]);
|
||||
if (otype ~ "^((un)?signed +)?int *$")
|
||||
var_opt_int[n_opt_int++] = name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?short *$")
|
||||
var_opt_short[n_opt_short++] = name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?char *$") {
|
||||
var_opt_char[n_opt_char++] = name;
|
||||
if (otype ~ "^unsigned +char *$")
|
||||
var_opt_range[name] = "0, 255"
|
||||
else if (otype ~ "^signed +char *$")
|
||||
var_opt_range[name] = "-128, 127"
|
||||
}
|
||||
else
|
||||
var_opt_other[n_opt_other++] = name;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_char; i++) {
|
||||
name = var_opt_char[i];
|
||||
if (var_opt_range[name] != "")
|
||||
print " gcc_assert (IN_RANGE (" name ", " var_opt_range[name] "));";
|
||||
}
|
||||
|
||||
print "";
|
||||
for (i = 0; i < n_opt_other; i++) {
|
||||
print " ptr->" var_opt_other[i] " = " var_opt_other[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_int; i++) {
|
||||
print " ptr->" var_opt_int[i] " = " var_opt_int[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_short; i++) {
|
||||
print " ptr->" var_opt_short[i] " = " var_opt_short[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_char; i++) {
|
||||
print " ptr->" var_opt_char[i] " = " var_opt_char[i] ";";
|
||||
}
|
||||
|
||||
print "}";
|
||||
|
||||
print "";
|
||||
print "/* Restore optimization options from a structure. */";
|
||||
print "void";
|
||||
print "cl_optimization_restore (struct cl_optimization *ptr)";
|
||||
print "{";
|
||||
|
||||
for (i = 0; i < n_opt_other; i++) {
|
||||
print " " var_opt_other[i] " = ptr->" var_opt_other[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_int; i++) {
|
||||
print " " var_opt_int[i] " = ptr->" var_opt_int[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_short; i++) {
|
||||
print " " var_opt_short[i] " = ptr->" var_opt_short[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_char; i++) {
|
||||
print " " var_opt_char[i] " = ptr->" var_opt_char[i] ";";
|
||||
}
|
||||
|
||||
print "}";
|
||||
|
||||
print "";
|
||||
print "/* Print optimization options from a structure. */";
|
||||
print "void";
|
||||
print "cl_optimization_print (FILE *file,";
|
||||
print " int indent_to,";
|
||||
print " struct cl_optimization *ptr)";
|
||||
print "{";
|
||||
|
||||
print " fputs (\"\\n\", file);";
|
||||
for (i = 0; i < n_opt_other; i++) {
|
||||
print " if (ptr->" var_opt_other[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%lx)\\n\",";
|
||||
print " indent_to, \"\",";
|
||||
print " \"" var_opt_other[i] "\",";
|
||||
print " (unsigned long)ptr->" var_opt_other[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_int; i++) {
|
||||
print " if (ptr->" var_opt_int[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%x)\\n\",";
|
||||
print " indent_to, \"\",";
|
||||
print " \"" var_opt_int[i] "\",";
|
||||
print " ptr->" var_opt_int[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_short; i++) {
|
||||
print " if (ptr->" var_opt_short[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%x)\\n\",";
|
||||
print " indent_to, \"\",";
|
||||
print " \"" var_opt_short[i] "\",";
|
||||
print " ptr->" var_opt_short[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_char; i++) {
|
||||
print " if (ptr->" var_opt_char[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%x)\\n\",";
|
||||
print " indent_to, \"\",";
|
||||
print " \"" var_opt_char[i] "\",";
|
||||
print " ptr->" var_opt_char[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
print "}";
|
||||
|
||||
print "";
|
||||
print "/* Save selected option variables into a structure. */"
|
||||
print "void";
|
||||
print "cl_target_option_save (struct cl_target_option *ptr)";
|
||||
print "{";
|
||||
|
||||
n_target_char = 0;
|
||||
n_target_short = 0;
|
||||
n_target_int = 0;
|
||||
n_target_other = 0;
|
||||
|
||||
if (have_save) {
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
if (flag_set_p("Save", flags[i])) {
|
||||
name = var_name(flags[i])
|
||||
if(name == "")
|
||||
name = "target_flags";
|
||||
|
||||
if(name in var_save_seen)
|
||||
continue;
|
||||
|
||||
var_save_seen[name]++;
|
||||
otype = var_type_struct(flags[i])
|
||||
if (otype ~ "^((un)?signed +)?int *$")
|
||||
var_target_int[n_target_int++] = name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?short *$")
|
||||
var_target_short[n_target_short++] = name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?char *$") {
|
||||
var_target_char[n_target_char++] = name;
|
||||
if (otype ~ "^unsigned +char *$")
|
||||
var_target_range[name] = "0, 255"
|
||||
else if (otype ~ "^signed +char *$")
|
||||
var_target_range[name] = "-128, 127"
|
||||
}
|
||||
else
|
||||
var_target_other[n_target_other++] = name;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var_target_int[n_target_int++] = "target_flags";
|
||||
}
|
||||
|
||||
have_assert = 0;
|
||||
for (i = 0; i < n_target_char; i++) {
|
||||
name = var_target_char[i];
|
||||
if (var_target_range[name] != "") {
|
||||
have_assert = 1;
|
||||
print " gcc_assert (IN_RANGE (" name ", " var_target_range[name] "));";
|
||||
}
|
||||
}
|
||||
|
||||
if (have_assert)
|
||||
print "";
|
||||
|
||||
print " if (targetm.target_option.save)";
|
||||
print " targetm.target_option.save (ptr);";
|
||||
print "";
|
||||
|
||||
for (i = 0; i < n_target_other; i++) {
|
||||
print " ptr->" var_target_other[i] " = " var_target_other[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_int; i++) {
|
||||
print " ptr->" var_target_int[i] " = " var_target_int[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_short; i++) {
|
||||
print " ptr->" var_target_short[i] " = " var_target_short[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_char; i++) {
|
||||
print " ptr->" var_target_char[i] " = " var_target_char[i] ";";
|
||||
}
|
||||
|
||||
print "}";
|
||||
|
||||
print "";
|
||||
print "/* Restore selected current options from a structure. */";
|
||||
print "void";
|
||||
print "cl_target_option_restore (struct cl_target_option *ptr)";
|
||||
print "{";
|
||||
|
||||
for (i = 0; i < n_target_other; i++) {
|
||||
print " " var_target_other[i] " = ptr->" var_target_other[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_int; i++) {
|
||||
print " " var_target_int[i] " = ptr->" var_target_int[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_short; i++) {
|
||||
print " " var_target_short[i] " = ptr->" var_target_short[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_char; i++) {
|
||||
print " " var_target_char[i] " = ptr->" var_target_char[i] ";";
|
||||
}
|
||||
|
||||
# This must occur after the normal variables in case the code depends on those
|
||||
# variables.
|
||||
print "";
|
||||
print " if (targetm.target_option.restore)";
|
||||
print " targetm.target_option.restore (ptr);";
|
||||
|
||||
print "}";
|
||||
|
||||
print "";
|
||||
print "/* Print optimization options from a structure. */";
|
||||
print "void";
|
||||
print "cl_target_option_print (FILE *file,";
|
||||
print " int indent,";
|
||||
print " struct cl_target_option *ptr)";
|
||||
print "{";
|
||||
|
||||
print " fputs (\"\\n\", file);";
|
||||
for (i = 0; i < n_target_other; i++) {
|
||||
print " if (ptr->" var_target_other[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%lx)\\n\",";
|
||||
print " indent, \"\",";
|
||||
print " \"" var_target_other[i] "\",";
|
||||
print " (unsigned long)ptr->" var_target_other[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_int; i++) {
|
||||
print " if (ptr->" var_target_int[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%x)\\n\",";
|
||||
print " indent, \"\",";
|
||||
print " \"" var_target_int[i] "\",";
|
||||
print " ptr->" var_target_int[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_short; i++) {
|
||||
print " if (ptr->" var_target_short[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%x)\\n\",";
|
||||
print " indent, \"\",";
|
||||
print " \"" var_target_short[i] "\",";
|
||||
print " ptr->" var_target_short[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_char; i++) {
|
||||
print " if (ptr->" var_target_char[i] ")";
|
||||
print " fprintf (file, \"%*s%s (0x%x)\\n\",";
|
||||
print " indent, \"\",";
|
||||
print " \"" var_target_char[i] "\",";
|
||||
print " ptr->" var_target_char[i] ");";
|
||||
print "";
|
||||
}
|
||||
|
||||
print "";
|
||||
print " if (targetm.target_option.print)";
|
||||
print " targetm.target_option.print (file, indent, ptr);";
|
||||
|
||||
print "}";
|
||||
print "#endif";
|
||||
|
||||
}
|
||||
|
|
171
gcc/opth-gen.awk
171
gcc/opth-gen.awk
|
@ -26,6 +26,7 @@
|
|||
BEGIN {
|
||||
n_opts = 0
|
||||
n_langs = 0
|
||||
n_target_save = 0
|
||||
n_extra_masks = 0
|
||||
quote = "\042"
|
||||
comma = ","
|
||||
|
@ -38,6 +39,11 @@ BEGIN {
|
|||
langs[n_langs] = $2
|
||||
n_langs++;
|
||||
}
|
||||
else if ($1 == "TargetSave") {
|
||||
# Make sure the declarations are put in source order
|
||||
target_save_decl[n_target_save] = $2
|
||||
n_target_save++
|
||||
}
|
||||
else {
|
||||
name = opt_args("Mask", $1)
|
||||
if (name == "") {
|
||||
|
@ -64,15 +70,180 @@ print "extern int target_flags;"
|
|||
print "extern int target_flags_explicit;"
|
||||
print ""
|
||||
|
||||
have_save = 0;
|
||||
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
if (flag_set_p("Save", flags[i]))
|
||||
have_save = 1;
|
||||
|
||||
name = var_name(flags[i]);
|
||||
if (name == "")
|
||||
continue;
|
||||
|
||||
if (name in var_seen)
|
||||
continue;
|
||||
|
||||
var_seen[name] = 1;
|
||||
print "extern " var_type(flags[i]) name ";"
|
||||
}
|
||||
print ""
|
||||
|
||||
# All of the optimization switches gathered together so they can be saved and restored.
|
||||
# This will allow attribute((cold)) to turn on space optimization.
|
||||
|
||||
# Change the type of normal switches from int to unsigned char to save space.
|
||||
# Also, order the structure so that pointer fields occur first, then int
|
||||
# fields, and then char fields to provide the best packing.
|
||||
|
||||
print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2)"
|
||||
print ""
|
||||
print "/* Structure to save/restore optimization and target specific options. */";
|
||||
print "struct cl_optimization GTY(())";
|
||||
print "{";
|
||||
|
||||
n_opt_char = 2;
|
||||
n_opt_short = 0;
|
||||
n_opt_int = 0;
|
||||
n_opt_other = 0;
|
||||
var_opt_char[0] = "unsigned char optimize";
|
||||
var_opt_char[1] = "unsigned char optimize_size";
|
||||
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
if (flag_set_p("Optimization", flags[i])) {
|
||||
name = var_name(flags[i])
|
||||
if(name == "")
|
||||
continue;
|
||||
|
||||
if(name in var_opt_seen)
|
||||
continue;
|
||||
|
||||
var_opt_seen[name]++;
|
||||
otype = var_type_struct(flags[i]);
|
||||
if (otype ~ "^((un)?signed +)?int *$")
|
||||
var_opt_int[n_opt_int++] = otype name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?short *$")
|
||||
var_opt_short[n_opt_short++] = otype name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?char *$")
|
||||
var_opt_char[n_opt_char++] = otype name;
|
||||
|
||||
else
|
||||
var_opt_other[n_opt_other++] = otype name;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_other; i++) {
|
||||
print " " var_opt_other[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_int; i++) {
|
||||
print " " var_opt_int[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_short; i++) {
|
||||
print " " var_opt_short[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_opt_char; i++) {
|
||||
print " " var_opt_char[i] ";";
|
||||
}
|
||||
|
||||
print "};";
|
||||
print "";
|
||||
|
||||
# Target and optimization save/restore/print functions.
|
||||
print "/* Structure to save/restore selected target specific options. */";
|
||||
print "struct cl_target_option GTY(())";
|
||||
print "{";
|
||||
|
||||
n_target_char = 0;
|
||||
n_target_short = 0;
|
||||
n_target_int = 0;
|
||||
n_target_other = 0;
|
||||
|
||||
for (i = 0; i < n_target_save; i++) {
|
||||
if (target_save_decl[i] ~ "^((un)?signed +)?int +[_a-zA-Z0-9]+$")
|
||||
var_target_int[n_target_int++] = target_save_decl[i];
|
||||
|
||||
else if (target_save_decl[i] ~ "^((un)?signed +)?short +[_a-zA-Z0-9]+$")
|
||||
var_target_short[n_target_short++] = target_save_decl[i];
|
||||
|
||||
else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_a-zA-Z0-9]+$")
|
||||
var_target_char[n_target_char++] = target_save_decl[i];
|
||||
|
||||
else
|
||||
var_target_other[n_target_other++] = target_save_decl[i];
|
||||
}
|
||||
|
||||
if (have_save) {
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
if (flag_set_p("Save", flags[i])) {
|
||||
name = var_name(flags[i])
|
||||
if(name == "")
|
||||
name = "target_flags";
|
||||
|
||||
if(name in var_save_seen)
|
||||
continue;
|
||||
|
||||
var_save_seen[name]++;
|
||||
otype = var_type_struct(flags[i])
|
||||
if (otype ~ "^((un)?signed +)?int *$")
|
||||
var_target_int[n_target_int++] = otype name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?short *$")
|
||||
var_target_short[n_target_short++] = otype name;
|
||||
|
||||
else if (otype ~ "^((un)?signed +)?char *$")
|
||||
var_target_char[n_target_char++] = otype name;
|
||||
|
||||
else
|
||||
var_target_other[n_target_other++] = otype name;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var_target_int[n_target_int++] = "int target_flags";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_other; i++) {
|
||||
print " " var_target_other[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_int; i++) {
|
||||
print " " var_target_int[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_short; i++) {
|
||||
print " " var_target_short[i] ";";
|
||||
}
|
||||
|
||||
for (i = 0; i < n_target_char; i++) {
|
||||
print " " var_target_char[i] ";";
|
||||
}
|
||||
|
||||
print "};";
|
||||
print "";
|
||||
print "";
|
||||
print "/* Save optimization variables into a structure. */"
|
||||
print "extern void cl_optimization_save (struct cl_optimization *);";
|
||||
print "";
|
||||
print "/* Restore optimization variables from a structure. */";
|
||||
print "extern void cl_optimization_restore (struct cl_optimization *);";
|
||||
print "";
|
||||
print "/* Print optimization variables from a structure. */";
|
||||
print "extern void cl_optimization_print (FILE *, int, struct cl_optimization *);";
|
||||
print "";
|
||||
print "/* Save selected option variables into a structure. */"
|
||||
print "extern void cl_target_option_save (struct cl_target_option *);";
|
||||
print "";
|
||||
print "/* Restore selected option variables from a structure. */"
|
||||
print "extern void cl_target_option_restore (struct cl_target_option *);";
|
||||
print "";
|
||||
print "/* Print target option variables from a structure. */";
|
||||
print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);";
|
||||
print "#endif";
|
||||
print "";
|
||||
|
||||
for (i = 0; i < n_opts; i++) {
|
||||
name = opt_args("Mask", flags[i])
|
||||
vname = var_name(flags[i])
|
||||
|
|
311
gcc/opts.c
311
gcc/opts.c
|
@ -809,12 +809,36 @@ handle_options (unsigned int argc, const char **argv, unsigned int lang_mask)
|
|||
void
|
||||
decode_options (unsigned int argc, const char **argv)
|
||||
{
|
||||
static bool first_time_p = true;
|
||||
static int initial_max_aliased_vops;
|
||||
static int initial_avg_aliased_vops;
|
||||
static int initial_min_crossjump_insns;
|
||||
static int initial_max_fields_for_field_sensitive;
|
||||
static unsigned int initial_lang_mask;
|
||||
|
||||
unsigned int i, lang_mask;
|
||||
int opt1;
|
||||
int opt2;
|
||||
int opt3;
|
||||
int opt1_max;
|
||||
|
||||
/* Perform language-specific options initialization. */
|
||||
lang_mask = lang_hooks.init_options (argc, argv);
|
||||
if (first_time_p)
|
||||
{
|
||||
/* Perform language-specific options initialization. */
|
||||
initial_lang_mask = lang_mask = lang_hooks.init_options (argc, argv);
|
||||
|
||||
lang_hooks.initialize_diagnostics (global_dc);
|
||||
lang_hooks.initialize_diagnostics (global_dc);
|
||||
|
||||
/* Save initial values of parameters we reset. */
|
||||
initial_max_aliased_vops = MAX_ALIASED_VOPS;
|
||||
initial_avg_aliased_vops = AVG_ALIASED_VOPS;
|
||||
initial_min_crossjump_insns
|
||||
= compiler_params[PARAM_MIN_CROSSJUMP_INSNS].value;
|
||||
initial_max_fields_for_field_sensitive
|
||||
= compiler_params[PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE].value;
|
||||
}
|
||||
else
|
||||
lang_mask = initial_lang_mask;
|
||||
|
||||
/* Scan to see what optimization level has been specified. That will
|
||||
determine the default value of many flags. */
|
||||
|
@ -863,6 +887,9 @@ decode_options (unsigned int argc, const char **argv)
|
|||
flag_section_anchors = 0;
|
||||
}
|
||||
|
||||
/* Originally we just set the variables if a particular optimization level,
|
||||
but with the advent of being able to change the optimization level for a
|
||||
function, we need to reset optimizations. */
|
||||
if (!optimize)
|
||||
{
|
||||
flag_merge_constants = 0;
|
||||
|
@ -873,139 +900,170 @@ decode_options (unsigned int argc, const char **argv)
|
|||
if (flag_toplevel_reorder == 2)
|
||||
flag_toplevel_reorder = 0;
|
||||
}
|
||||
else
|
||||
flag_merge_constants = 1;
|
||||
|
||||
if (optimize >= 1)
|
||||
{
|
||||
flag_defer_pop = 1;
|
||||
/* -O1 optimizations. */
|
||||
opt1 = (optimize >= 1);
|
||||
flag_defer_pop = opt1;
|
||||
#ifdef DELAY_SLOTS
|
||||
flag_delayed_branch = 1;
|
||||
flag_delayed_branch = opt1;
|
||||
#endif
|
||||
#ifdef CAN_DEBUG_WITHOUT_FP
|
||||
flag_omit_frame_pointer = 1;
|
||||
flag_omit_frame_pointer = opt1;
|
||||
#endif
|
||||
flag_guess_branch_prob = 1;
|
||||
flag_cprop_registers = 1;
|
||||
flag_if_conversion = 1;
|
||||
flag_if_conversion2 = 1;
|
||||
flag_ipa_pure_const = 1;
|
||||
flag_ipa_reference = 1;
|
||||
flag_split_wide_types = 1;
|
||||
flag_tree_ccp = 1;
|
||||
flag_tree_dce = 1;
|
||||
flag_tree_dom = 1;
|
||||
flag_tree_dse = 1;
|
||||
flag_tree_ter = 1;
|
||||
flag_tree_sra = 1;
|
||||
flag_tree_copyrename = 1;
|
||||
flag_tree_fre = 1;
|
||||
flag_tree_copy_prop = 1;
|
||||
flag_tree_sink = 1;
|
||||
flag_guess_branch_prob = opt1;
|
||||
flag_cprop_registers = opt1;
|
||||
flag_if_conversion = opt1;
|
||||
flag_if_conversion2 = opt1;
|
||||
flag_ipa_pure_const = opt1;
|
||||
flag_ipa_reference = opt1;
|
||||
flag_split_wide_types = opt1;
|
||||
flag_tree_ccp = opt1;
|
||||
flag_tree_dce = opt1;
|
||||
flag_tree_dom = opt1;
|
||||
flag_tree_dse = opt1;
|
||||
flag_tree_ter = opt1;
|
||||
flag_tree_sra = opt1;
|
||||
flag_tree_copyrename = opt1;
|
||||
flag_tree_fre = opt1;
|
||||
flag_tree_copy_prop = opt1;
|
||||
flag_tree_sink = opt1;
|
||||
flag_tree_ch = opt1;
|
||||
|
||||
if (!optimize_size)
|
||||
{
|
||||
/* Loop header copying usually increases size of the code. This used
|
||||
not to be true, since quite often it is possible to verify that
|
||||
the condition is satisfied in the first iteration and therefore
|
||||
to eliminate it. Jump threading handles these cases now. */
|
||||
flag_tree_ch = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (optimize >= 2)
|
||||
{
|
||||
flag_inline_small_functions = 1;
|
||||
flag_thread_jumps = 1;
|
||||
flag_crossjumping = 1;
|
||||
flag_optimize_sibling_calls = 1;
|
||||
flag_forward_propagate = 1;
|
||||
flag_cse_follow_jumps = 1;
|
||||
flag_gcse = 1;
|
||||
flag_expensive_optimizations = 1;
|
||||
flag_rerun_cse_after_loop = 1;
|
||||
flag_caller_saves = 1;
|
||||
flag_peephole2 = 1;
|
||||
/* -O2 optimizations. */
|
||||
opt2 = (optimize >= 2);
|
||||
flag_inline_small_functions = opt2;
|
||||
flag_thread_jumps = opt2;
|
||||
flag_crossjumping = opt2;
|
||||
flag_optimize_sibling_calls = opt2;
|
||||
flag_forward_propagate = opt2;
|
||||
flag_cse_follow_jumps = opt2;
|
||||
flag_gcse = opt2;
|
||||
flag_expensive_optimizations = opt2;
|
||||
flag_rerun_cse_after_loop = opt2;
|
||||
flag_caller_saves = opt2;
|
||||
flag_peephole2 = opt2;
|
||||
#ifdef INSN_SCHEDULING
|
||||
flag_schedule_insns = 1;
|
||||
flag_schedule_insns_after_reload = 1;
|
||||
flag_schedule_insns = opt2;
|
||||
flag_schedule_insns_after_reload = opt2;
|
||||
#endif
|
||||
flag_regmove = 1;
|
||||
flag_strict_aliasing = 1;
|
||||
flag_strict_overflow = 1;
|
||||
flag_delete_null_pointer_checks = 1;
|
||||
flag_reorder_blocks = 1;
|
||||
flag_reorder_functions = 1;
|
||||
flag_tree_store_ccp = 1;
|
||||
flag_tree_vrp = 1;
|
||||
flag_regmove = opt2;
|
||||
flag_strict_aliasing = opt2;
|
||||
flag_strict_overflow = opt2;
|
||||
flag_delete_null_pointer_checks = opt2;
|
||||
flag_reorder_blocks = opt2;
|
||||
flag_reorder_functions = opt2;
|
||||
flag_tree_store_ccp = opt2;
|
||||
flag_tree_vrp = opt2;
|
||||
flag_tree_builtin_call_dce = opt2;
|
||||
flag_tree_pre = opt2;
|
||||
flag_tree_switch_conversion = 1;
|
||||
|
||||
if (!optimize_size)
|
||||
{
|
||||
/* Conditional DCE generates bigger code. */
|
||||
flag_tree_builtin_call_dce = 1;
|
||||
/* PRE tends to generate bigger code. */
|
||||
flag_tree_pre = 1;
|
||||
}
|
||||
|
||||
/* Allow more virtual operators to increase alias precision. */
|
||||
set_param_value ("max-aliased-vops", 500);
|
||||
|
||||
/* Track fields in field-sensitive alias analysis. */
|
||||
set_param_value ("max-fields-for-field-sensitive", 100);
|
||||
}
|
||||
set_param_value ("max-aliased-vops",
|
||||
(opt2) ? 500 : initial_max_aliased_vops);
|
||||
|
||||
if (optimize >= 3)
|
||||
/* Track fields in field-sensitive alias analysis. */
|
||||
set_param_value ("max-fields-for-field-sensitive",
|
||||
(opt2) ? 100 : initial_max_fields_for_field_sensitive);
|
||||
|
||||
/* -O3 optimizations. */
|
||||
opt3 = (optimize >= 3);
|
||||
flag_predictive_commoning = opt3;
|
||||
flag_inline_functions = opt3;
|
||||
flag_unswitch_loops = opt3;
|
||||
flag_gcse_after_reload = opt3;
|
||||
flag_tree_vectorize = opt3;
|
||||
|
||||
/* Allow even more virtual operators. Max-aliased-vops was set above for
|
||||
-O2, so don't reset it unless we are at -O3. */
|
||||
if (opt3)
|
||||
set_param_value ("max-aliased-vops", 1000);
|
||||
|
||||
set_param_value ("avg-aliased-vops", (opt3) ? 3 : initial_avg_aliased_vops);
|
||||
|
||||
/* Just -O1/-O0 optimizations. */
|
||||
opt1_max = (optimize <= 1);
|
||||
align_loops = opt1_max;
|
||||
align_jumps = opt1_max;
|
||||
align_labels = opt1_max;
|
||||
align_functions = opt1_max;
|
||||
|
||||
if (optimize_size)
|
||||
{
|
||||
flag_predictive_commoning = 1;
|
||||
/* Loop header copying usually increases size of the code. This used not to
|
||||
be true, since quite often it is possible to verify that the condition is
|
||||
satisfied in the first iteration and therefore to eliminate it. Jump
|
||||
threading handles these cases now. */
|
||||
flag_tree_ch = 0;
|
||||
|
||||
/* Conditional DCE generates bigger code. */
|
||||
flag_tree_builtin_call_dce = 0;
|
||||
|
||||
/* PRE tends to generate bigger code. */
|
||||
flag_tree_pre = 0;
|
||||
|
||||
/* These options are set with -O3, so reset for -Os */
|
||||
flag_predictive_commoning = 0;
|
||||
flag_inline_functions = 0;
|
||||
flag_unswitch_loops = 0;
|
||||
flag_gcse_after_reload = 0;
|
||||
flag_tree_vectorize = 0;
|
||||
|
||||
/* Don't reorder blocks when optimizing for size because extra jump insns may
|
||||
be created; also barrier may create extra padding.
|
||||
|
||||
More correctly we should have a block reordering mode that tried to
|
||||
minimize the combined size of all the jumps. This would more or less
|
||||
automatically remove extra jumps, but would also try to use more short
|
||||
jumps instead of long jumps. */
|
||||
flag_reorder_blocks = 0;
|
||||
flag_reorder_blocks_and_partition = 0;
|
||||
|
||||
/* Inlining of functions reducing size is a good idea regardless of them
|
||||
being declared inline. */
|
||||
flag_inline_functions = 1;
|
||||
flag_unswitch_loops = 1;
|
||||
flag_gcse_after_reload = 1;
|
||||
flag_tree_vectorize = 1;
|
||||
|
||||
/* Allow even more virtual operators. */
|
||||
set_param_value ("max-aliased-vops", 1000);
|
||||
set_param_value ("avg-aliased-vops", 3);
|
||||
}
|
||||
|
||||
if (optimize < 2 || optimize_size)
|
||||
{
|
||||
/* Don't align code. */
|
||||
align_loops = 1;
|
||||
align_jumps = 1;
|
||||
align_labels = 1;
|
||||
align_functions = 1;
|
||||
|
||||
/* Don't reorder blocks when optimizing for size because extra
|
||||
jump insns may be created; also barrier may create extra padding.
|
||||
/* Unroll/prefetch switches that may be set on the command line, and tend to
|
||||
generate bigger code. */
|
||||
flag_unroll_loops = 0;
|
||||
flag_unroll_all_loops = 0;
|
||||
flag_prefetch_loop_arrays = 0;
|
||||
|
||||
More correctly we should have a block reordering mode that tried
|
||||
to minimize the combined size of all the jumps. This would more
|
||||
or less automatically remove extra jumps, but would also try to
|
||||
use more short jumps instead of long jumps. */
|
||||
flag_reorder_blocks = 0;
|
||||
flag_reorder_blocks_and_partition = 0;
|
||||
}
|
||||
|
||||
if (optimize_size)
|
||||
{
|
||||
/* Inlining of functions reducing size is a good idea regardless
|
||||
of them being declared inline. */
|
||||
flag_inline_functions = 1;
|
||||
/* Basic optimization options. */
|
||||
optimize_size = 1;
|
||||
if (optimize > 2)
|
||||
optimize = 2;
|
||||
|
||||
/* We want to crossjump as much as possible. */
|
||||
set_param_value ("min-crossjump-insns", 1);
|
||||
}
|
||||
else
|
||||
set_param_value ("min-crossjump-insns", initial_min_crossjump_insns);
|
||||
|
||||
/* Initialize whether `char' is signed. */
|
||||
flag_signed_char = DEFAULT_SIGNED_CHAR;
|
||||
/* Set this to a special "uninitialized" value. The actual default is set
|
||||
after target options have been processed. */
|
||||
flag_short_enums = 2;
|
||||
if (first_time_p)
|
||||
{
|
||||
/* Initialize whether `char' is signed. */
|
||||
flag_signed_char = DEFAULT_SIGNED_CHAR;
|
||||
/* Set this to a special "uninitialized" value. The actual default is
|
||||
set after target options have been processed. */
|
||||
flag_short_enums = 2;
|
||||
|
||||
/* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
|
||||
modify it. */
|
||||
target_flags = targetm.default_target_flags;
|
||||
/* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
|
||||
modify it. */
|
||||
target_flags = targetm.default_target_flags;
|
||||
|
||||
/* Some targets have ABI-specified unwind tables. */
|
||||
flag_unwind_tables = targetm.unwind_tables_default;
|
||||
/* Some targets have ABI-specified unwind tables. */
|
||||
flag_unwind_tables = targetm.unwind_tables_default;
|
||||
}
|
||||
|
||||
#ifdef OPTIMIZATION_OPTIONS
|
||||
/* Allow default optimizations to be specified on a per-machine basis. */
|
||||
|
@ -1014,15 +1072,18 @@ decode_options (unsigned int argc, const char **argv)
|
|||
|
||||
handle_options (argc, argv, lang_mask);
|
||||
|
||||
if (flag_pie)
|
||||
flag_pic = flag_pie;
|
||||
if (flag_pic && !flag_pie)
|
||||
flag_shlib = 1;
|
||||
if (first_time_p)
|
||||
{
|
||||
if (flag_pie)
|
||||
flag_pic = flag_pie;
|
||||
if (flag_pic && !flag_pie)
|
||||
flag_shlib = 1;
|
||||
|
||||
if (flag_no_inline == 2)
|
||||
flag_no_inline = 0;
|
||||
else
|
||||
flag_really_no_inline = flag_no_inline;
|
||||
if (flag_no_inline == 2)
|
||||
flag_no_inline = 0;
|
||||
else
|
||||
flag_really_no_inline = flag_no_inline;
|
||||
}
|
||||
|
||||
/* Set flag_no_inline before the post_options () hook. The C front
|
||||
ends use it to determine tree inlining defaults. FIXME: such
|
||||
|
@ -1095,6 +1156,14 @@ decode_options (unsigned int argc, const char **argv)
|
|||
flag_reorder_blocks_and_partition = 0;
|
||||
flag_reorder_blocks = 1;
|
||||
}
|
||||
|
||||
/* Save the current optimization options if this is the first call. */
|
||||
if (first_time_p)
|
||||
{
|
||||
optimization_default_node = build_optimization_node ();
|
||||
optimization_current_node = optimization_default_node;
|
||||
first_time_p = false;
|
||||
}
|
||||
}
|
||||
|
||||
#define LEFT_COLUMN 27
|
||||
|
@ -2087,6 +2156,18 @@ fast_math_flags_set_p (void)
|
|||
&& !flag_errno_math);
|
||||
}
|
||||
|
||||
/* Return true iff flags are set as if -ffast-math but using the flags stored
|
||||
in the struct cl_optimization structure. */
|
||||
bool
|
||||
fast_math_flags_struct_set_p (struct cl_optimization *opt)
|
||||
{
|
||||
return (!opt->flag_trapping_math
|
||||
&& opt->flag_unsafe_math_optimizations
|
||||
&& opt->flag_finite_math_only
|
||||
&& !opt->flag_signed_zeros
|
||||
&& !opt->flag_errno_math);
|
||||
}
|
||||
|
||||
/* Handle a debug output -g switch. EXTENDED is true or false to support
|
||||
extended output (2 is special and means "-ggdb" was given). */
|
||||
static void
|
||||
|
|
|
@ -369,6 +369,12 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
|
|||
if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
|
||||
fputs (" suppress-debug", file);
|
||||
|
||||
if (TREE_CODE (node) == FUNCTION_DECL
|
||||
&& DECL_FUNCTION_SPECIFIC_TARGET (node))
|
||||
fputs (" function-specific-target", file);
|
||||
if (TREE_CODE (node) == FUNCTION_DECL
|
||||
&& DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node))
|
||||
fputs (" function-specific-opt", file);
|
||||
if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
|
||||
fputs (DECL_DECLARED_INLINE_P (node) ? " inline" : " autoinline", file);
|
||||
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node))
|
||||
|
@ -931,6 +937,14 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
|
|||
}
|
||||
break;
|
||||
|
||||
case OPTIMIZATION_NODE:
|
||||
cl_optimization_print (file, indent + 4, TREE_OPTIMIZATION (node));
|
||||
break;
|
||||
|
||||
case TARGET_OPTION_NODE:
|
||||
cl_target_option_print (file, indent + 4, TREE_TARGET_OPTION (node));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (EXCEPTIONAL_CLASS_P (node))
|
||||
lang_hooks.print_xnode (file, node, indent);
|
||||
|
|
|
@ -758,6 +758,41 @@
|
|||
TARGET_EMUTLS_DEBUG_FORM_TLS_ADDRESS \
|
||||
}
|
||||
|
||||
/* Function specific option attribute support. */
|
||||
#ifndef TARGET_OPTION_VALID_ATTRIBUTE_P
|
||||
#define TARGET_OPTION_VALID_ATTRIBUTE_P NULL
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_OPTION_SAVE
|
||||
#define TARGET_OPTION_SAVE NULL
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_OPTION_RESTORE
|
||||
#define TARGET_OPTION_RESTORE NULL
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_OPTION_PRINT
|
||||
#define TARGET_OPTION_PRINT NULL
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_OPTION_PRAGMA_PARSE
|
||||
#define TARGET_OPTION_PRAGMA_PARSE NULL
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_OPTION_CAN_INLINE_P
|
||||
#define TARGET_OPTION_CAN_INLINE_P default_target_option_can_inline_p
|
||||
#endif
|
||||
|
||||
#define TARGET_OPTION_HOOKS \
|
||||
{ \
|
||||
TARGET_OPTION_VALID_ATTRIBUTE_P, \
|
||||
TARGET_OPTION_SAVE, \
|
||||
TARGET_OPTION_RESTORE, \
|
||||
TARGET_OPTION_PRINT, \
|
||||
TARGET_OPTION_PRAGMA_PARSE, \
|
||||
TARGET_OPTION_CAN_INLINE_P, \
|
||||
}
|
||||
|
||||
/* The whole shebang. */
|
||||
#define TARGET_INITIALIZER \
|
||||
{ \
|
||||
|
@ -854,6 +889,7 @@
|
|||
TARGET_C, \
|
||||
TARGET_CXX, \
|
||||
TARGET_EMUTLS, \
|
||||
TARGET_OPTION_HOOKS, \
|
||||
TARGET_EXTRA_LIVE_ON_ENTRY, \
|
||||
TARGET_UNWIND_TABLES_DEFAULT, \
|
||||
TARGET_HAVE_NAMED_SECTIONS, \
|
||||
|
|
28
gcc/target.h
28
gcc/target.h
|
@ -963,6 +963,34 @@ struct gcc_target
|
|||
bool debug_form_tls_address;
|
||||
} emutls;
|
||||
|
||||
struct target_option_hooks {
|
||||
/* Function to validate the attribute((option(...))) strings or NULL. If
|
||||
the option is validated, it is assumed that DECL_FUNCTION_SPECIFIC will
|
||||
be filled in in the function decl node. */
|
||||
bool (*valid_attribute_p) (tree, tree, tree, int);
|
||||
|
||||
/* Function to save any extra target state in the target options
|
||||
structure. */
|
||||
void (*save) (struct cl_target_option *);
|
||||
|
||||
/* Function to restore any extra target state from the target options
|
||||
structure. */
|
||||
void (*restore) (struct cl_target_option *);
|
||||
|
||||
/* Function to print any extra target state from the target options
|
||||
structure. */
|
||||
void (*print) (FILE *, int, struct cl_target_option *);
|
||||
|
||||
/* Function to parse arguments to be validated for #pragma option, and to
|
||||
change the state if the options are valid. If the arguments are NULL,
|
||||
use the default target options. Return true if the options are valid,
|
||||
and set the current state. */
|
||||
bool (*pragma_parse) (tree);
|
||||
|
||||
/* Function to determine if one function can inline another function. */
|
||||
bool (*can_inline_p) (tree, tree);
|
||||
} target_option;
|
||||
|
||||
/* For targets that need to mark extra registers as live on entry to
|
||||
the function, they should define this target hook and set their
|
||||
bits in the bitmap passed in. */
|
||||
|
|
|
@ -709,4 +709,38 @@ default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
default_target_option_valid_attribute_p (tree ARG_UNUSED (fndecl),
|
||||
tree ARG_UNUSED (name),
|
||||
tree ARG_UNUSED (args),
|
||||
int ARG_UNUSED (flags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
default_target_option_can_inline_p (tree caller, tree callee)
|
||||
{
|
||||
bool ret = false;
|
||||
tree callee_opts = DECL_FUNCTION_SPECIFIC_TARGET (callee);
|
||||
tree caller_opts = DECL_FUNCTION_SPECIFIC_TARGET (caller);
|
||||
|
||||
/* If callee has no option attributes, then it is ok to inline */
|
||||
if (!callee_opts)
|
||||
ret = true;
|
||||
|
||||
/* If caller has no option attributes, but callee does then it is not ok to
|
||||
inline */
|
||||
else if (!caller_opts)
|
||||
ret = false;
|
||||
|
||||
/* If both caller and callee have attributes, assume that if the pointer is
|
||||
different, the the two functions have different target options since
|
||||
build_target_option_node uses a hash table for the options. */
|
||||
else
|
||||
ret = (callee_opts == caller_opts);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "gt-targhooks.h"
|
||||
|
|
|
@ -97,5 +97,6 @@ extern int default_reloc_rw_mask (void);
|
|||
extern tree default_mangle_decl_assembler_name (tree, tree);
|
||||
extern tree default_emutls_var_fields (tree, tree *);
|
||||
extern tree default_emutls_var_init (tree, tree, tree);
|
||||
|
||||
extern bool default_hard_regno_scratch_ok (unsigned int);
|
||||
extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
|
||||
extern bool default_target_option_can_inline_p (tree, tree);
|
||||
|
|
13
gcc/testsuite/gcc.target/i386/cold-1.c
Normal file
13
gcc/testsuite/gcc.target/i386/cold-1.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* Test whether using attribute((cold)) really turns on -Os. Do this test
|
||||
by checking whether strcpy calls the library function rather than doing
|
||||
the move inline. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3 -march=k8" } */
|
||||
/* { dg-final { scan-assembler "(jmp|call)\t(.*)strcpy" } } */
|
||||
|
||||
void cold (char *) __attribute__((__cold__));
|
||||
|
||||
void cold (char *a)
|
||||
{
|
||||
__builtin_strcpy (a, "testing 1.2.3 testing 1.2.3");
|
||||
}
|
34
gcc/testsuite/gcc.target/i386/funcspec-1.c
Normal file
34
gcc/testsuite/gcc.target/i386/funcspec-1.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Test whether using target specific options, we can generate SSE2 code on
|
||||
32-bit, which does not generate SSE2 by default, but still generate 387 code
|
||||
for a function that doesn't use attribute((option)). */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
/* { dg-options "-O3 -ftree-vectorize -march=i386" } */
|
||||
/* { dg-final { scan-assembler "addps\[ \t\]" } } */
|
||||
/* { dg-final { scan-assembler "fsubs\[ \t\]" } } */
|
||||
|
||||
#ifndef SIZE
|
||||
#define SIZE 1024
|
||||
#endif
|
||||
|
||||
static float a[SIZE] __attribute__((__aligned__(16)));
|
||||
static float b[SIZE] __attribute__((__aligned__(16)));
|
||||
static float c[SIZE] __attribute__((__aligned__(16)));
|
||||
|
||||
void sse_addnums (void) __attribute__ ((__option__ ("sse2")));
|
||||
|
||||
void
|
||||
sse_addnums (void)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < SIZE; ++i)
|
||||
a[i] = b[i] + c[i];
|
||||
}
|
||||
|
||||
void
|
||||
i387_subnums (void)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < SIZE; ++i)
|
||||
a[i] = b[i] - c[i];
|
||||
}
|
99
gcc/testsuite/gcc.target/i386/funcspec-2.c
Normal file
99
gcc/testsuite/gcc.target/i386/funcspec-2.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* Test whether using target specific options, we can generate SSE5 code. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target lp64 } */
|
||||
/* { dg-options "-O2 -march=k8" } */
|
||||
|
||||
extern void exit (int);
|
||||
|
||||
#define SSE5_ATTR __attribute__((__option__("sse5,fused-madd")))
|
||||
extern float flt_mul_add (float a, float b, float c) SSE5_ATTR;
|
||||
extern float flt_mul_sub (float a, float b, float c) SSE5_ATTR;
|
||||
extern float flt_neg_mul_add (float a, float b, float c) SSE5_ATTR;
|
||||
extern float flt_neg_mul_sub (float a, float b, float c) SSE5_ATTR;
|
||||
|
||||
extern double dbl_mul_add (double a, double b, double c) SSE5_ATTR;
|
||||
extern double dbl_mul_sub (double a, double b, double c) SSE5_ATTR;
|
||||
extern double dbl_neg_mul_add (double a, double b, double c) SSE5_ATTR;
|
||||
extern double dbl_neg_mul_sub (double a, double b, double c) SSE5_ATTR;
|
||||
|
||||
float
|
||||
flt_mul_add (float a, float b, float c)
|
||||
{
|
||||
return (a * b) + c;
|
||||
}
|
||||
|
||||
double
|
||||
dbl_mul_add (double a, double b, double c)
|
||||
{
|
||||
return (a * b) + c;
|
||||
}
|
||||
|
||||
float
|
||||
flt_mul_sub (float a, float b, float c)
|
||||
{
|
||||
return (a * b) - c;
|
||||
}
|
||||
|
||||
double
|
||||
dbl_mul_sub (double a, double b, double c)
|
||||
{
|
||||
return (a * b) - c;
|
||||
}
|
||||
|
||||
float
|
||||
flt_neg_mul_add (float a, float b, float c)
|
||||
{
|
||||
return (-(a * b)) + c;
|
||||
}
|
||||
|
||||
double
|
||||
dbl_neg_mul_add (double a, double b, double c)
|
||||
{
|
||||
return (-(a * b)) + c;
|
||||
}
|
||||
|
||||
float
|
||||
flt_neg_mul_sub (float a, float b, float c)
|
||||
{
|
||||
return (-(a * b)) - c;
|
||||
}
|
||||
|
||||
double
|
||||
dbl_neg_mul_sub (double a, double b, double c)
|
||||
{
|
||||
return (-(a * b)) - c;
|
||||
}
|
||||
|
||||
float f[10] = { 2, 3, 4 };
|
||||
double d[10] = { 2, 3, 4 };
|
||||
|
||||
int main ()
|
||||
{
|
||||
f[3] = flt_mul_add (f[0], f[1], f[2]);
|
||||
f[4] = flt_mul_sub (f[0], f[1], f[2]);
|
||||
f[5] = flt_neg_mul_add (f[0], f[1], f[2]);
|
||||
f[6] = flt_neg_mul_sub (f[0], f[1], f[2]);
|
||||
|
||||
d[3] = dbl_mul_add (d[0], d[1], d[2]);
|
||||
d[4] = dbl_mul_sub (d[0], d[1], d[2]);
|
||||
d[5] = dbl_neg_mul_add (d[0], d[1], d[2]);
|
||||
d[6] = dbl_neg_mul_sub (d[0], d[1], d[2]);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "fmaddss" } } */
|
||||
/* { dg-final { scan-assembler "fmaddsd" } } */
|
||||
/* { dg-final { scan-assembler "fmsubss" } } */
|
||||
/* { dg-final { scan-assembler "fmsubsd" } } */
|
||||
/* { dg-final { scan-assembler "fnmaddss" } } */
|
||||
/* { dg-final { scan-assembler "fnmaddsd" } } */
|
||||
/* { dg-final { scan-assembler "fnmsubss" } } */
|
||||
/* { dg-final { scan-assembler "fnmsubsd" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)flt_mul_add" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)flt_mul_sub" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)flt_neg_mul_add" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)flt_neg_mul_sub" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)dbl_mul_add" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)dbl_mul_sub" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)dbl_neg_mul_add" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)dbl_neg_mul_sub" } } */
|
66
gcc/testsuite/gcc.target/i386/funcspec-3.c
Normal file
66
gcc/testsuite/gcc.target/i386/funcspec-3.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Test whether using target specific options, we can generate popcnt by
|
||||
setting the architecture. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target lp64 } */
|
||||
/* { dg-options "-O2 -march=k8" } */
|
||||
|
||||
extern void exit (int);
|
||||
extern void abort (void);
|
||||
|
||||
#define SSE4A_ATTR __attribute__((__option__("arch=amdfam10")))
|
||||
#define SSE42_ATTR __attribute__((__option__("sse4.2")))
|
||||
|
||||
static int sse4a_pop_i (int a) SSE4A_ATTR;
|
||||
static long sse42_pop_l (long a) SSE42_ATTR;
|
||||
static int generic_pop_i (int a);
|
||||
static long generic_pop_l (long a);
|
||||
|
||||
static
|
||||
int sse4a_pop_i (int a)
|
||||
{
|
||||
return __builtin_popcount (a);
|
||||
}
|
||||
|
||||
static
|
||||
long sse42_pop_l (long a)
|
||||
{
|
||||
return __builtin_popcountl (a);
|
||||
}
|
||||
|
||||
static
|
||||
int generic_pop_i (int a)
|
||||
{
|
||||
return __builtin_popcount (a);
|
||||
}
|
||||
|
||||
static
|
||||
long generic_pop_l (long a)
|
||||
{
|
||||
return __builtin_popcountl (a);
|
||||
}
|
||||
|
||||
int five = 5;
|
||||
long seven = 7;
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (sse4a_pop_i (five) != 2)
|
||||
abort ();
|
||||
|
||||
if (sse42_pop_l (seven) != 3L)
|
||||
abort ();
|
||||
|
||||
if (generic_pop_i (five) != 2)
|
||||
abort ();
|
||||
|
||||
if (generic_pop_l (seven) != 3L)
|
||||
abort ();
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "popcntl" } } */
|
||||
/* { dg-final { scan-assembler "popcntq" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)sse4a_pop_i" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)sse42_pop_l" } } */
|
||||
/* { dg-final { scan-assembler "call\t(.*)popcountdi2" } } */
|
14
gcc/testsuite/gcc.target/i386/funcspec-4.c
Normal file
14
gcc/testsuite/gcc.target/i386/funcspec-4.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* Test some error conditions with function specific options. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* no sse500 switch */
|
||||
extern void error1 (void) __attribute__((__option__("sse500"))); /* { dg-error "unknown" } */
|
||||
|
||||
/* Multiple arch switches */
|
||||
extern void error2 (void) __attribute__((__option__("arch=core2,arch=k8"))); /* { dg-error "already specified" } */
|
||||
|
||||
/* Unknown tune target */
|
||||
extern void error3 (void) __attribute__((__option__("tune=foobar"))); /* { dg-error "bad value" } */
|
||||
|
||||
/* option on a variable */
|
||||
extern int error4 __attribute__((__option__("sse2"))); /* { dg-warning "ignored" } */
|
125
gcc/testsuite/gcc.target/i386/funcspec-5.c
Normal file
125
gcc/testsuite/gcc.target/i386/funcspec-5.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* Test whether all of the 32-bit function specific options are accepted
|
||||
without error. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
|
||||
extern void test_abm (void) __attribute__((__option__("abm")));
|
||||
extern void test_aes (void) __attribute__((__option__("aes")));
|
||||
extern void test_fused_madd (void) __attribute__((__option__("fused-madd")));
|
||||
extern void test_mmx (void) __attribute__((__option__("mmx")));
|
||||
extern void test_pclmul (void) __attribute__((__option__("pclmul")));
|
||||
extern void test_popcnt (void) __attribute__((__option__("popcnt")));
|
||||
extern void test_recip (void) __attribute__((__option__("recip")));
|
||||
extern void test_sse (void) __attribute__((__option__("sse")));
|
||||
extern void test_sse2 (void) __attribute__((__option__("sse2")));
|
||||
extern void test_sse3 (void) __attribute__((__option__("sse3")));
|
||||
extern void test_sse4 (void) __attribute__((__option__("sse4")));
|
||||
extern void test_sse4_1 (void) __attribute__((__option__("sse4.1")));
|
||||
extern void test_sse4_2 (void) __attribute__((__option__("sse4.2")));
|
||||
extern void test_sse4a (void) __attribute__((__option__("sse4a")));
|
||||
extern void test_sse5 (void) __attribute__((__option__("sse5")));
|
||||
extern void test_ssse3 (void) __attribute__((__option__("ssse3")));
|
||||
|
||||
extern void test_no_abm (void) __attribute__((__option__("no-abm")));
|
||||
extern void test_no_aes (void) __attribute__((__option__("no-aes")));
|
||||
extern void test_no_fused_madd (void) __attribute__((__option__("no-fused-madd")));
|
||||
extern void test_no_mmx (void) __attribute__((__option__("no-mmx")));
|
||||
extern void test_no_pclmul (void) __attribute__((__option__("no-pclmul")));
|
||||
extern void test_no_popcnt (void) __attribute__((__option__("no-popcnt")));
|
||||
extern void test_no_recip (void) __attribute__((__option__("no-recip")));
|
||||
extern void test_no_sse (void) __attribute__((__option__("no-sse")));
|
||||
extern void test_no_sse2 (void) __attribute__((__option__("no-sse2")));
|
||||
extern void test_no_sse3 (void) __attribute__((__option__("no-sse3")));
|
||||
extern void test_no_sse4 (void) __attribute__((__option__("no-sse4")));
|
||||
extern void test_no_sse4_1 (void) __attribute__((__option__("no-sse4.1")));
|
||||
extern void test_no_sse4_2 (void) __attribute__((__option__("no-sse4.2")));
|
||||
extern void test_no_sse4a (void) __attribute__((__option__("no-sse4a")));
|
||||
extern void test_no_sse5 (void) __attribute__((__option__("no-sse5")));
|
||||
extern void test_no_ssse3 (void) __attribute__((__option__("no-ssse3")));
|
||||
|
||||
extern void test_arch_i386 (void) __attribute__((__option__("arch=i386")));
|
||||
extern void test_arch_i486 (void) __attribute__((__option__("arch=i486")));
|
||||
extern void test_arch_i586 (void) __attribute__((__option__("arch=i586")));
|
||||
extern void test_arch_pentium (void) __attribute__((__option__("arch=pentium")));
|
||||
extern void test_arch_pentium_mmx (void) __attribute__((__option__("arch=pentium-mmx")));
|
||||
extern void test_arch_winchip_c6 (void) __attribute__((__option__("arch=winchip-c6")));
|
||||
extern void test_arch_winchip2 (void) __attribute__((__option__("arch=winchip2")));
|
||||
extern void test_arch_c3 (void) __attribute__((__option__("arch=c3")));
|
||||
extern void test_arch_c3_2 (void) __attribute__((__option__("arch=c3-2")));
|
||||
extern void test_arch_i686 (void) __attribute__((__option__("arch=i686")));
|
||||
extern void test_arch_pentiumpro (void) __attribute__((__option__("arch=pentiumpro")));
|
||||
extern void test_arch_pentium2 (void) __attribute__((__option__("arch=pentium2")));
|
||||
extern void test_arch_pentium3 (void) __attribute__((__option__("arch=pentium3")));
|
||||
extern void test_arch_pentium3m (void) __attribute__((__option__("arch=pentium3m")));
|
||||
extern void test_arch_pentium_m (void) __attribute__((__option__("arch=pentium-m")));
|
||||
extern void test_arch_pentium4 (void) __attribute__((__option__("arch=pentium4")));
|
||||
extern void test_arch_pentium4m (void) __attribute__((__option__("arch=pentium4m")));
|
||||
extern void test_arch_prescott (void) __attribute__((__option__("arch=prescott")));
|
||||
extern void test_arch_nocona (void) __attribute__((__option__("arch=nocona")));
|
||||
extern void test_arch_core2 (void) __attribute__((__option__("arch=core2")));
|
||||
extern void test_arch_geode (void) __attribute__((__option__("arch=geode")));
|
||||
extern void test_arch_k6 (void) __attribute__((__option__("arch=k6")));
|
||||
extern void test_arch_k6_2 (void) __attribute__((__option__("arch=k6-2")));
|
||||
extern void test_arch_k6_3 (void) __attribute__((__option__("arch=k6-3")));
|
||||
extern void test_arch_athlon (void) __attribute__((__option__("arch=athlon")));
|
||||
extern void test_arch_athlon_tbird (void) __attribute__((__option__("arch=athlon-tbird")));
|
||||
extern void test_arch_athlon_4 (void) __attribute__((__option__("arch=athlon-4")));
|
||||
extern void test_arch_athlon_xp (void) __attribute__((__option__("arch=athlon-xp")));
|
||||
extern void test_arch_athlon_mp (void) __attribute__((__option__("arch=athlon-mp")));
|
||||
extern void test_arch_k8 (void) __attribute__((__option__("arch=k8")));
|
||||
extern void test_arch_k8_sse3 (void) __attribute__((__option__("arch=k8-sse3")));
|
||||
extern void test_arch_opteron (void) __attribute__((__option__("arch=opteron")));
|
||||
extern void test_arch_opteron_sse3 (void) __attribute__((__option__("arch=opteron-sse3")));
|
||||
extern void test_arch_athlon64 (void) __attribute__((__option__("arch=athlon64")));
|
||||
extern void test_arch_athlon64_sse3 (void) __attribute__((__option__("arch=athlon64-sse3")));
|
||||
extern void test_arch_athlon_fx (void) __attribute__((__option__("arch=athlon-fx")));
|
||||
extern void test_arch_amdfam10 (void) __attribute__((__option__("arch=amdfam10")));
|
||||
extern void test_arch_barcelona (void) __attribute__((__option__("arch=barcelona")));
|
||||
extern void test_arch_foo (void) __attribute__((__option__("arch=foo"))); /* { dg-error "bad value" } */
|
||||
|
||||
extern void test_tune_i386 (void) __attribute__((__option__("tune=i386")));
|
||||
extern void test_tune_i486 (void) __attribute__((__option__("tune=i486")));
|
||||
extern void test_tune_i586 (void) __attribute__((__option__("tune=i586")));
|
||||
extern void test_tune_pentium (void) __attribute__((__option__("tune=pentium")));
|
||||
extern void test_tune_pentium_mmx (void) __attribute__((__option__("tune=pentium-mmx")));
|
||||
extern void test_tune_winchip_c6 (void) __attribute__((__option__("tune=winchip-c6")));
|
||||
extern void test_tune_winchip2 (void) __attribute__((__option__("tune=winchip2")));
|
||||
extern void test_tune_c3 (void) __attribute__((__option__("tune=c3")));
|
||||
extern void test_tune_c3_2 (void) __attribute__((__option__("tune=c3-2")));
|
||||
extern void test_tune_i686 (void) __attribute__((__option__("tune=i686")));
|
||||
extern void test_tune_pentiumpro (void) __attribute__((__option__("tune=pentiumpro")));
|
||||
extern void test_tune_pentium2 (void) __attribute__((__option__("tune=pentium2")));
|
||||
extern void test_tune_pentium3 (void) __attribute__((__option__("tune=pentium3")));
|
||||
extern void test_tune_pentium3m (void) __attribute__((__option__("tune=pentium3m")));
|
||||
extern void test_tune_pentium_m (void) __attribute__((__option__("tune=pentium-m")));
|
||||
extern void test_tune_pentium4 (void) __attribute__((__option__("tune=pentium4")));
|
||||
extern void test_tune_pentium4m (void) __attribute__((__option__("tune=pentium4m")));
|
||||
extern void test_tune_prescott (void) __attribute__((__option__("tune=prescott")));
|
||||
extern void test_tune_nocona (void) __attribute__((__option__("tune=nocona")));
|
||||
extern void test_tune_core2 (void) __attribute__((__option__("tune=core2")));
|
||||
extern void test_tune_geode (void) __attribute__((__option__("tune=geode")));
|
||||
extern void test_tune_k6 (void) __attribute__((__option__("tune=k6")));
|
||||
extern void test_tune_k6_2 (void) __attribute__((__option__("tune=k6-2")));
|
||||
extern void test_tune_k6_3 (void) __attribute__((__option__("tune=k6-3")));
|
||||
extern void test_tune_athlon (void) __attribute__((__option__("tune=athlon")));
|
||||
extern void test_tune_athlon_tbird (void) __attribute__((__option__("tune=athlon-tbird")));
|
||||
extern void test_tune_athlon_4 (void) __attribute__((__option__("tune=athlon-4")));
|
||||
extern void test_tune_athlon_xp (void) __attribute__((__option__("tune=athlon-xp")));
|
||||
extern void test_tune_athlon_mp (void) __attribute__((__option__("tune=athlon-mp")));
|
||||
extern void test_tune_k8 (void) __attribute__((__option__("tune=k8")));
|
||||
extern void test_tune_k8_sse3 (void) __attribute__((__option__("tune=k8-sse3")));
|
||||
extern void test_tune_opteron (void) __attribute__((__option__("tune=opteron")));
|
||||
extern void test_tune_opteron_sse3 (void) __attribute__((__option__("tune=opteron-sse3")));
|
||||
extern void test_tune_athlon64 (void) __attribute__((__option__("tune=athlon64")));
|
||||
extern void test_tune_athlon64_sse3 (void) __attribute__((__option__("tune=athlon64-sse3")));
|
||||
extern void test_tune_athlon_fx (void) __attribute__((__option__("tune=athlon-fx")));
|
||||
extern void test_tune_amdfam10 (void) __attribute__((__option__("tune=amdfam10")));
|
||||
extern void test_tune_barcelona (void) __attribute__((__option__("tune=barcelona")));
|
||||
extern void test_tune_generic (void) __attribute__((__option__("tune=generic")));
|
||||
extern void test_tune_foo (void) __attribute__((__option__("tune=foo"))); /* { dg-error "bad value" } */
|
||||
|
||||
extern void test_fpmath_sse (void) __attribute__((__option__("sse2,fpmath=sse")));
|
||||
extern void test_fpmath_387 (void) __attribute__((__option__("sse2,fpmath=387")));
|
||||
extern void test_fpmath_sse_387 (void) __attribute__((__option__("sse2,fpmath=sse+387")));
|
||||
extern void test_fpmath_387_sse (void) __attribute__((__option__("sse2,fpmath=387+sse")));
|
||||
extern void test_fpmath_both (void) __attribute__((__option__("sse2,fpmath=both")));
|
71
gcc/testsuite/gcc.target/i386/funcspec-6.c
Normal file
71
gcc/testsuite/gcc.target/i386/funcspec-6.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Test whether all of the 64-bit function specific options are accepted
|
||||
without error. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target lp64 } */
|
||||
|
||||
extern void test_abm (void) __attribute__((__option__("abm")));
|
||||
extern void test_aes (void) __attribute__((__option__("aes")));
|
||||
extern void test_fused_madd (void) __attribute__((__option__("fused-madd")));
|
||||
extern void test_mmx (void) __attribute__((__option__("mmx")));
|
||||
extern void test_pclmul (void) __attribute__((__option__("pclmul")));
|
||||
extern void test_popcnt (void) __attribute__((__option__("popcnt")));
|
||||
extern void test_recip (void) __attribute__((__option__("recip")));
|
||||
extern void test_sse (void) __attribute__((__option__("sse")));
|
||||
extern void test_sse2 (void) __attribute__((__option__("sse2")));
|
||||
extern void test_sse3 (void) __attribute__((__option__("sse3")));
|
||||
extern void test_sse4 (void) __attribute__((__option__("sse4")));
|
||||
extern void test_sse4_1 (void) __attribute__((__option__("sse4.1")));
|
||||
extern void test_sse4_2 (void) __attribute__((__option__("sse4.2")));
|
||||
extern void test_sse4a (void) __attribute__((__option__("sse4a")));
|
||||
extern void test_sse5 (void) __attribute__((__option__("sse5")));
|
||||
extern void test_ssse3 (void) __attribute__((__option__("ssse3")));
|
||||
|
||||
extern void test_no_abm (void) __attribute__((__option__("no-abm")));
|
||||
extern void test_no_aes (void) __attribute__((__option__("no-aes")));
|
||||
extern void test_no_fused_madd (void) __attribute__((__option__("no-fused-madd")));
|
||||
extern void test_no_mmx (void) __attribute__((__option__("no-mmx")));
|
||||
extern void test_no_pclmul (void) __attribute__((__option__("no-pclmul")));
|
||||
extern void test_no_popcnt (void) __attribute__((__option__("no-popcnt")));
|
||||
extern void test_no_recip (void) __attribute__((__option__("no-recip")));
|
||||
extern void test_no_sse (void) __attribute__((__option__("no-sse")));
|
||||
extern void test_no_sse2 (void) __attribute__((__option__("no-sse2")));
|
||||
extern void test_no_sse3 (void) __attribute__((__option__("no-sse3")));
|
||||
extern void test_no_sse4 (void) __attribute__((__option__("no-sse4")));
|
||||
extern void test_no_sse4_1 (void) __attribute__((__option__("no-sse4.1")));
|
||||
extern void test_no_sse4_2 (void) __attribute__((__option__("no-sse4.2")));
|
||||
extern void test_no_sse4a (void) __attribute__((__option__("no-sse4a")));
|
||||
extern void test_no_sse5 (void) __attribute__((__option__("no-sse5")));
|
||||
extern void test_no_ssse3 (void) __attribute__((__option__("no-ssse3")));
|
||||
|
||||
extern void test_arch_nocona (void) __attribute__((__option__("arch=nocona")));
|
||||
extern void test_arch_core2 (void) __attribute__((__option__("arch=core2")));
|
||||
extern void test_arch_k8 (void) __attribute__((__option__("arch=k8")));
|
||||
extern void test_arch_k8_sse3 (void) __attribute__((__option__("arch=k8-sse3")));
|
||||
extern void test_arch_opteron (void) __attribute__((__option__("arch=opteron")));
|
||||
extern void test_arch_opteron_sse3 (void) __attribute__((__option__("arch=opteron-sse3")));
|
||||
extern void test_arch_athlon64 (void) __attribute__((__option__("arch=athlon64")));
|
||||
extern void test_arch_athlon64_sse3 (void) __attribute__((__option__("arch=athlon64-sse3")));
|
||||
extern void test_arch_athlon_fx (void) __attribute__((__option__("arch=athlon-fx")));
|
||||
extern void test_arch_amdfam10 (void) __attribute__((__option__("arch=amdfam10")));
|
||||
extern void test_arch_barcelona (void) __attribute__((__option__("arch=barcelona")));
|
||||
extern void test_arch_foo (void) __attribute__((__option__("arch=foo"))); /* { dg-error "bad value" } */
|
||||
|
||||
extern void test_tune_nocona (void) __attribute__((__option__("tune=nocona")));
|
||||
extern void test_tune_core2 (void) __attribute__((__option__("tune=core2")));
|
||||
extern void test_tune_k8 (void) __attribute__((__option__("tune=k8")));
|
||||
extern void test_tune_k8_sse3 (void) __attribute__((__option__("tune=k8-sse3")));
|
||||
extern void test_tune_opteron (void) __attribute__((__option__("tune=opteron")));
|
||||
extern void test_tune_opteron_sse3 (void) __attribute__((__option__("tune=opteron-sse3")));
|
||||
extern void test_tune_athlon64 (void) __attribute__((__option__("tune=athlon64")));
|
||||
extern void test_tune_athlon64_sse3 (void) __attribute__((__option__("tune=athlon64-sse3")));
|
||||
extern void test_tune_athlon_fx (void) __attribute__((__option__("tune=athlon-fx")));
|
||||
extern void test_tune_amdfam10 (void) __attribute__((__option__("tune=amdfam10")));
|
||||
extern void test_tune_barcelona (void) __attribute__((__option__("tune=barcelona")));
|
||||
extern void test_tune_generic (void) __attribute__((__option__("tune=generic")));
|
||||
extern void test_tune_foo (void) __attribute__((__option__("tune=foo"))); /* { dg-error "bad value" } */
|
||||
|
||||
extern void test_fpmath_sse (void) __attribute__((__option__("sse2,fpmath=sse")));
|
||||
extern void test_fpmath_387 (void) __attribute__((__option__("sse2,fpmath=387")));
|
||||
extern void test_fpmath_sse_387 (void) __attribute__((__option__("sse2,fpmath=sse+387")));
|
||||
extern void test_fpmath_387_sse (void) __attribute__((__option__("sse2,fpmath=387+sse")));
|
||||
extern void test_fpmath_both (void) __attribute__((__option__("sse2,fpmath=both")));
|
13
gcc/testsuite/gcc.target/i386/funcspec-7.c
Normal file
13
gcc/testsuite/gcc.target/i386/funcspec-7.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* Test whether using target specific options, we can generate the reciprocal
|
||||
square root instruction. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -march=k8 -mno-recip -mfpmath=sse -ffast-math" } */
|
||||
|
||||
float do_recip (float a) __attribute__((__option__("recip")));
|
||||
float do_normal (float a);
|
||||
|
||||
float do_recip (float a) { return 1.0f / __builtin_sqrtf (a); }
|
||||
float do_normal (float a) { return 1.0f / __builtin_sqrtf (a); }
|
||||
|
||||
/* { dg-final { scan-assembler "sqrtss" } } */
|
||||
/* { dg-final { scan-assembler "rsqrtss" } } */
|
161
gcc/testsuite/gcc.target/i386/funcspec-8.c
Normal file
161
gcc/testsuite/gcc.target/i386/funcspec-8.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* Test whether using target specific options, we can use the x86 builtin
|
||||
functions in functions with the appropriate function specific options. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -march=k8 -mfpmath=sse" } */
|
||||
|
||||
typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
|
||||
typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
|
||||
typedef int __m128w __attribute__ ((__vector_size__ (16), __may_alias__));
|
||||
typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__));
|
||||
|
||||
#ifdef __SSE3__
|
||||
#error "-msse3 should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128d sse3_hsubpd (__m128d a, __m128d b) __attribute__((__option__("sse3")));
|
||||
__m128d generic_hsubpd (__m128d a, __m128d b);
|
||||
|
||||
__m128d
|
||||
sse3_hsubpd (__m128d a, __m128d b)
|
||||
{
|
||||
return __builtin_ia32_hsubpd (a, b);
|
||||
}
|
||||
|
||||
__m128d
|
||||
generic_hsubpd (__m128d a, __m128d b)
|
||||
{
|
||||
return __builtin_ia32_hsubpd (a, b); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __SSSE3__
|
||||
#error "-mssse3 should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128w ssse3_psignd128 (__m128w a, __m128w b) __attribute__((__option__("ssse3")));
|
||||
__m128w generic_psignd (__m128w ab, __m128w b);
|
||||
|
||||
__m128w
|
||||
ssse3_psignd128 (__m128w a, __m128w b)
|
||||
{
|
||||
return __builtin_ia32_psignd128 (a, b);
|
||||
}
|
||||
|
||||
__m128w
|
||||
generic_psignd128 (__m128w a, __m128w b)
|
||||
{
|
||||
return __builtin_ia32_psignd128 (a, b); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
#error "-msse4.1 should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128d sse4_1_blendvpd (__m128d a, __m128d b, __m128d c) __attribute__((__option__("sse4.1")));
|
||||
__m128d generic_blendvpd (__m128d a, __m128d b, __m128d c);
|
||||
|
||||
__m128d
|
||||
sse4_1_blendvpd (__m128d a, __m128d b, __m128d c)
|
||||
{
|
||||
return __builtin_ia32_blendvpd (a, b, c);
|
||||
}
|
||||
|
||||
__m128d
|
||||
generic_blendvpd (__m128d a, __m128d b, __m128d c)
|
||||
{
|
||||
return __builtin_ia32_blendvpd (a, b, c); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __SSE4_2__
|
||||
#error "-msse4.2 should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128i sse4_2_pcmpgtq (__m128i a, __m128i b) __attribute__((__option__("sse4.2")));
|
||||
__m128i generic_pcmpgtq (__m128i ab, __m128i b);
|
||||
|
||||
__m128i
|
||||
sse4_2_pcmpgtq (__m128i a, __m128i b)
|
||||
{
|
||||
return __builtin_ia32_pcmpgtq (a, b);
|
||||
}
|
||||
|
||||
__m128i
|
||||
generic_pcmpgtq (__m128i a, __m128i b)
|
||||
{
|
||||
return __builtin_ia32_pcmpgtq (a, b); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __SSE4A__
|
||||
#error "-msse4a should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128i sse4_2_insertq (__m128i a, __m128i b) __attribute__((__option__("sse4a")));
|
||||
__m128i generic_insertq (__m128i ab, __m128i b);
|
||||
|
||||
__m128i
|
||||
sse4_2_insertq (__m128i a, __m128i b)
|
||||
{
|
||||
return __builtin_ia32_insertq (a, b);
|
||||
}
|
||||
|
||||
__m128i
|
||||
generic_insertq (__m128i a, __m128i b)
|
||||
{
|
||||
return __builtin_ia32_insertq (a, b); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __SSE5__
|
||||
#error "-msse5 should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128d sse5_fmaddpd (__m128d a, __m128d b, __m128d c) __attribute__((__option__("sse5")));
|
||||
__m128d generic_fmaddpd (__m128d a, __m128d b, __m128d c);
|
||||
|
||||
__m128d
|
||||
sse5_fmaddpd (__m128d a, __m128d b, __m128d c)
|
||||
{
|
||||
return __builtin_ia32_fmaddpd (a, b, c);
|
||||
}
|
||||
|
||||
__m128d
|
||||
generic_fmaddpd (__m128d a, __m128d b, __m128d c)
|
||||
{
|
||||
return __builtin_ia32_fmaddpd (a, b, c); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __AES__
|
||||
#error "-maes should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128i aes_aesimc128 (__m128i a) __attribute__((__option__("aes")));
|
||||
__m128i generic_aesimc128 (__m128i a);
|
||||
|
||||
__m128i
|
||||
aes_aesimc128 (__m128i a)
|
||||
{
|
||||
return __builtin_ia32_aesimc128 (a);
|
||||
}
|
||||
|
||||
__m128i
|
||||
generic_aesimc128 (__m128i a)
|
||||
{
|
||||
return __builtin_ia32_aesimc128 (a); /* { dg-error "needs isa option" } */
|
||||
}
|
||||
|
||||
#ifdef __PCLMUL__
|
||||
#error "-mpclmul should not be set for this test"
|
||||
#endif
|
||||
|
||||
__m128i pclmul_pclmulqdq128 (__m128i a, __m128i b) __attribute__((__option__("pclmul")));
|
||||
__m128i generic_pclmulqdq128 (__m128i a, __m128i b);
|
||||
|
||||
__m128i
|
||||
pclmul_pclmulqdq128 (__m128i a, __m128i b)
|
||||
{
|
||||
return __builtin_ia32_pclmulqdq128 (a, b, 5);
|
||||
}
|
||||
|
||||
__m128i
|
||||
generic_pclmulqdq128 (__m128i a, __m128i b)
|
||||
{
|
||||
return __builtin_ia32_pclmulqdq128 (a, b, 5); /* { dg-error "needs isa option" } */
|
||||
}
|
36
gcc/testsuite/gcc.target/i386/funcspec-9.c
Normal file
36
gcc/testsuite/gcc.target/i386/funcspec-9.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* Test whether using target specific options, we can generate SSE5 code. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -march=k8 -mfpmath=sse -msse2" } */
|
||||
|
||||
extern void exit (int);
|
||||
|
||||
#ifdef __SSE5__
|
||||
#warning "__SSE5__ should not be defined before #pragma GCC option."
|
||||
#endif
|
||||
|
||||
#pragma GCC option (push)
|
||||
#pragma GCC option ("sse5,fused-madd")
|
||||
|
||||
#ifndef __SSE5__
|
||||
#warning "__SSE5__ should have be defined after #pragma GCC option."
|
||||
#endif
|
||||
|
||||
float
|
||||
flt_mul_add (float a, float b, float c)
|
||||
{
|
||||
return (a * b) + c;
|
||||
}
|
||||
|
||||
#pragma GCC option (pop)
|
||||
#ifdef __SSE5__
|
||||
#warning "__SSE5__ should not be defined after #pragma GCC pop option."
|
||||
#endif
|
||||
|
||||
double
|
||||
dbl_mul_add (double a, double b, double c)
|
||||
{
|
||||
return (a * b) + c;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "fmaddss" } } */
|
||||
/* { dg-final { scan-assembler "addsd" } } */
|
33
gcc/testsuite/gcc.target/i386/hot-1.c
Normal file
33
gcc/testsuite/gcc.target/i386/hot-1.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Test whether using attribute((hot)) really turns on -O3. Do this test
|
||||
by checking whether we vectorize a simple loop. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -msse2 -mfpmath=sse -march=k8" } */
|
||||
/* { dg-final { scan-assembler "addps" } } */
|
||||
/* { dg-final { scan-assembler "subss" } } */
|
||||
|
||||
#define SIZE 1024
|
||||
float a[SIZE] __attribute__((__aligned__(32)));
|
||||
float b[SIZE] __attribute__((__aligned__(32)));
|
||||
float c[SIZE] __attribute__((__aligned__(32)));
|
||||
|
||||
/* This should vectorize. */
|
||||
void hot (void) __attribute__((__hot__));
|
||||
|
||||
void
|
||||
hot (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i++)
|
||||
a[i] = b[i] + c[i];
|
||||
}
|
||||
|
||||
/* This should not vectorize. */
|
||||
void
|
||||
not_hot (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i++)
|
||||
a[i] = b[i] - c[i];
|
||||
}
|
35
gcc/testsuite/gcc.target/i386/opt-1.c
Normal file
35
gcc/testsuite/gcc.target/i386/opt-1.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Test the attribute((optimize)) really works. Do this test by checking
|
||||
whether we vectorize a simple loop. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -msse2 -mfpmath=sse -march=k8" } */
|
||||
/* { dg-final { scan-assembler "prefetcht0" } } */
|
||||
/* { dg-final { scan-assembler "addps" } } */
|
||||
/* { dg-final { scan-assembler "subss" } } */
|
||||
|
||||
#define SIZE 10240
|
||||
float a[SIZE] __attribute__((__aligned__(32)));
|
||||
float b[SIZE] __attribute__((__aligned__(32)));
|
||||
float c[SIZE] __attribute__((__aligned__(32)));
|
||||
|
||||
/* This should vectorize. */
|
||||
void opt3 (void) __attribute__((__optimize__(3,"unroll-all-loops,-fprefetch-loop-arrays")));
|
||||
|
||||
void
|
||||
opt3 (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i++)
|
||||
a[i] = b[i] + c[i];
|
||||
}
|
||||
|
||||
/* This should not vectorize. */
|
||||
void
|
||||
not_opt3 (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i++)
|
||||
a[i] = b[i] - c[i];
|
||||
}
|
||||
|
38
gcc/testsuite/gcc.target/i386/opt-2.c
Normal file
38
gcc/testsuite/gcc.target/i386/opt-2.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Test the attribute((optimize)) really works. Do this test by checking
|
||||
whether we vectorize a simple loop. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -msse2 -mfpmath=sse -march=k8" } */
|
||||
/* { dg-final { scan-assembler "prefetcht0" } } */
|
||||
/* { dg-final { scan-assembler "addps" } } */
|
||||
/* { dg-final { scan-assembler "subss" } } */
|
||||
|
||||
#define SIZE 10240
|
||||
float a[SIZE] __attribute__((__aligned__(32)));
|
||||
float b[SIZE] __attribute__((__aligned__(32)));
|
||||
float c[SIZE] __attribute__((__aligned__(32)));
|
||||
|
||||
/* This should vectorize. */
|
||||
#pragma GCC optimize push
|
||||
#pragma GCC optimize (3, "unroll-all-loops", "-fprefetch-loop-arrays")
|
||||
|
||||
void
|
||||
opt3 (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i++)
|
||||
a[i] = b[i] + c[i];
|
||||
}
|
||||
|
||||
#pragma GCC optimize pop
|
||||
|
||||
/* This should not vectorize. */
|
||||
void
|
||||
not_opt3 (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i++)
|
||||
a[i] = b[i] - c[i];
|
||||
}
|
||||
|
171
gcc/testsuite/gcc.target/i386/sse-22.c
Normal file
171
gcc/testsuite/gcc.target/i386/sse-22.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
/* Same as sse-14, except converted to use #pragma GCC option. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -Werror-implicit-function-declaration" } */
|
||||
|
||||
#include <mm_malloc.h>
|
||||
|
||||
/* Test that the intrinsics compile without optimization. All of them are
|
||||
defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h and mm3dnow.h
|
||||
that reference the proper builtin functions. Defining away "extern" and
|
||||
"__inline" results in all of them being compiled as proper functions. */
|
||||
|
||||
#define extern
|
||||
#define __inline
|
||||
|
||||
#define _CONCAT(x,y) x ## y
|
||||
|
||||
#define test_1(func, type, op1_type, imm) \
|
||||
type _CONCAT(_,func) (op1_type A, int const I) \
|
||||
{ return func (A, imm); }
|
||||
|
||||
#define test_1x(func, type, op1_type, imm1, imm2) \
|
||||
type _CONCAT(_,func) (op1_type A, int const I, int const L) \
|
||||
{ return func (A, imm1, imm2); }
|
||||
|
||||
#define test_2(func, type, op1_type, op2_type, imm) \
|
||||
type _CONCAT(_,func) (op1_type A, op2_type B, int const I) \
|
||||
{ return func (A, B, imm); }
|
||||
|
||||
#define test_2x(func, type, op1_type, op2_type, imm1, imm2) \
|
||||
type _CONCAT(_,func) (op1_type A, op2_type B, int const I, int const L) \
|
||||
{ return func (A, B, imm1, imm2); }
|
||||
|
||||
#define test_4(func, type, op1_type, op2_type, op3_type, op4_type, imm) \
|
||||
type _CONCAT(_,func) (op1_type A, op2_type B, \
|
||||
op3_type C, op4_type D, int const I) \
|
||||
{ return func (A, B, C, D, imm); }
|
||||
|
||||
|
||||
#ifndef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse5,aes,pclmul")
|
||||
#endif
|
||||
|
||||
/* Following intrinsics require immediate arguments. They
|
||||
are defined as macros for non-optimized compilations. */
|
||||
|
||||
/* mmintrin.h (MMX). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("mmx")
|
||||
#endif
|
||||
#include <mmintrin.h>
|
||||
|
||||
/* mm3dnow.h (3DNOW). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("3dnow")
|
||||
#endif
|
||||
#include <mm3dnow.h>
|
||||
|
||||
/* xmmintrin.h (SSE). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("sse")
|
||||
#endif
|
||||
#include <xmmintrin.h>
|
||||
test_2 (_mm_shuffle_ps, __m128, __m128, __m128, 1)
|
||||
test_1 (_mm_extract_pi16, int, __m64, 1)
|
||||
test_1 (_m_pextrw, int, __m64, 1)
|
||||
test_2 (_mm_insert_pi16, __m64, __m64, int, 1)
|
||||
test_2 (_m_pinsrw, __m64, __m64, int, 1)
|
||||
test_1 (_mm_shuffle_pi16, __m64, __m64, 1)
|
||||
test_1 (_m_pshufw, __m64, __m64, 1)
|
||||
test_1 (_mm_prefetch, void, void *, _MM_HINT_NTA)
|
||||
|
||||
/* emmintrin.h (SSE2). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("sse2")
|
||||
#endif
|
||||
#include <emmintrin.h>
|
||||
test_2 (_mm_shuffle_pd, __m128d, __m128d, __m128d, 1)
|
||||
test_1 (_mm_srli_si128, __m128i, __m128i, 1)
|
||||
test_1 (_mm_slli_si128, __m128i, __m128i, 1)
|
||||
test_1 (_mm_extract_epi16, int, __m128i, 1)
|
||||
test_2 (_mm_insert_epi16, __m128i, __m128i, int, 1)
|
||||
test_1 (_mm_shufflehi_epi16, __m128i, __m128i, 1)
|
||||
test_1 (_mm_shufflelo_epi16, __m128i, __m128i, 1)
|
||||
test_1 (_mm_shuffle_epi32, __m128i, __m128i, 1)
|
||||
|
||||
/* pmmintrin.h (SSE3). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("sse3")
|
||||
#endif
|
||||
#include <pmmintrin.h>
|
||||
|
||||
/* tmmintrin.h (SSSE3). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("ssse3")
|
||||
#endif
|
||||
#include <tmmintrin.h>
|
||||
test_2 (_mm_alignr_epi8, __m128i, __m128i, __m128i, 1)
|
||||
test_2 (_mm_alignr_pi8, __m64, __m64, __m64, 1)
|
||||
|
||||
/* ammintrin.h (SSE4A). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("sse4a")
|
||||
#endif
|
||||
#include <ammintrin.h>
|
||||
test_1x (_mm_extracti_si64, __m128i, __m128i, 1, 1)
|
||||
test_2x (_mm_inserti_si64, __m128i, __m128i, __m128i, 1, 1)
|
||||
|
||||
/* smmintrin.h (SSE4.1). */
|
||||
/* nmmintrin.h (SSE4.2). */
|
||||
/* Note, nmmintrin.h includes smmintrin.h, and smmintrin.h checks for the
|
||||
#ifdef. So just set the option to SSE4.2. */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("sse4.2")
|
||||
#endif
|
||||
#include <nmmintrin.h>
|
||||
test_2 (_mm_blend_epi16, __m128i, __m128i, __m128i, 1)
|
||||
test_2 (_mm_blend_ps, __m128, __m128, __m128, 1)
|
||||
test_2 (_mm_blend_pd, __m128d, __m128d, __m128d, 1)
|
||||
test_2 (_mm_dp_ps, __m128, __m128, __m128, 1)
|
||||
test_2 (_mm_dp_pd, __m128d, __m128d, __m128d, 1)
|
||||
test_2 (_mm_insert_ps, __m128, __m128, __m128, 1)
|
||||
test_1 (_mm_extract_ps, int, __m128, 1)
|
||||
test_2 (_mm_insert_epi8, __m128i, __m128i, int, 1)
|
||||
test_2 (_mm_insert_epi32, __m128i, __m128i, int, 1)
|
||||
#ifdef __x86_64__
|
||||
test_2 (_mm_insert_epi64, __m128i, __m128i, long long, 1)
|
||||
#endif
|
||||
test_1 (_mm_extract_epi8, int, __m128i, 1)
|
||||
test_1 (_mm_extract_epi32, int, __m128i, 1)
|
||||
#ifdef __x86_64__
|
||||
test_1 (_mm_extract_epi64, long long, __m128i, 1)
|
||||
#endif
|
||||
test_2 (_mm_mpsadbw_epu8, __m128i, __m128i, __m128i, 1)
|
||||
test_2 (_mm_cmpistrm, __m128i, __m128i, __m128i, 1)
|
||||
test_2 (_mm_cmpistri, int, __m128i, __m128i, 1)
|
||||
test_4 (_mm_cmpestrm, __m128i, __m128i, int, __m128i, int, 1)
|
||||
test_4 (_mm_cmpestri, int, __m128i, int, __m128i, int, 1)
|
||||
test_2 (_mm_cmpistra, int, __m128i, __m128i, 1)
|
||||
test_2 (_mm_cmpistrc, int, __m128i, __m128i, 1)
|
||||
test_2 (_mm_cmpistro, int, __m128i, __m128i, 1)
|
||||
test_2 (_mm_cmpistrs, int, __m128i, __m128i, 1)
|
||||
test_2 (_mm_cmpistrz, int, __m128i, __m128i, 1)
|
||||
test_4 (_mm_cmpestra, int, __m128i, int, __m128i, int, 1)
|
||||
test_4 (_mm_cmpestrc, int, __m128i, int, __m128i, int, 1)
|
||||
test_4 (_mm_cmpestro, int, __m128i, int, __m128i, int, 1)
|
||||
test_4 (_mm_cmpestrs, int, __m128i, int, __m128i, int, 1)
|
||||
test_4 (_mm_cmpestrz, int, __m128i, int, __m128i, int, 1)
|
||||
|
||||
/* bmmintrin.h (SSE5). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("sse5")
|
||||
#endif
|
||||
#include <bmmintrin.h>
|
||||
test_1 (_mm_roti_epi8, __m128i, __m128i, 1)
|
||||
test_1 (_mm_roti_epi16, __m128i, __m128i, 1)
|
||||
test_1 (_mm_roti_epi32, __m128i, __m128i, 1)
|
||||
test_1 (_mm_roti_epi64, __m128i, __m128i, 1)
|
||||
|
||||
/* wmmintrin.h (AES/PCLMUL). */
|
||||
#ifdef DIFFERENT_PRAGMAS
|
||||
#pragma GCC option ("aes,pclmul")
|
||||
#endif
|
||||
#include <wmmintrin.h>
|
||||
test_1 (_mm_aeskeygenassist_si128, __m128i, __m128i, 1)
|
||||
test_2 (_mm_clmulepi64_si128, __m128i, __m128i, __m128i, 1)
|
||||
|
||||
/* mmintrin-common.h */
|
||||
test_1 (_mm_round_pd, __m128d, __m128d, 1)
|
||||
test_1 (_mm_round_ps, __m128, __m128, 1)
|
||||
test_2 (_mm_round_sd, __m128d, __m128d, __m128d, 1)
|
||||
test_2 (_mm_round_ss, __m128, __m128, __m128, 1)
|
108
gcc/testsuite/gcc.target/i386/sse-23.c
Normal file
108
gcc/testsuite/gcc.target/i386/sse-23.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8" } */
|
||||
|
||||
#include <mm_malloc.h>
|
||||
|
||||
/* Test that the intrinsics compile with optimization. All of them are
|
||||
defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h and mm3dnow.h
|
||||
that reference the proper builtin functions. Defining away "extern" and
|
||||
"__inline" results in all of them being compiled as proper functions. */
|
||||
|
||||
#define extern
|
||||
#define __inline
|
||||
|
||||
/* Following intrinsics require immediate arguments. */
|
||||
|
||||
/* ammintrin.h */
|
||||
#define __builtin_ia32_extrqi(X, I, L) __builtin_ia32_extrqi(X, 1, 1)
|
||||
#define __builtin_ia32_insertqi(X, Y, I, L) __builtin_ia32_insertqi(X, Y, 1, 1)
|
||||
|
||||
/* wmmintrin.h */
|
||||
#define __builtin_ia32_aeskeygenassist128(X, C) __builtin_ia32_aeskeygenassist128(X, 1)
|
||||
#define __builtin_ia32_pclmulqdq128(X, Y, I) __builtin_ia32_pclmulqdq128(X, Y, 1)
|
||||
|
||||
/* mmintrin-common.h */
|
||||
#define __builtin_ia32_roundpd(V, M) __builtin_ia32_roundpd(V, 1)
|
||||
#define __builtin_ia32_roundsd(D, V, M) __builtin_ia32_roundsd(D, V, 1)
|
||||
#define __builtin_ia32_roundps(V, M) __builtin_ia32_roundps(V, 1)
|
||||
#define __builtin_ia32_roundss(D, V, M) __builtin_ia32_roundss(D, V, 1)
|
||||
|
||||
/* smmintrin.h */
|
||||
#define __builtin_ia32_pblendw128(X, Y, M) __builtin_ia32_pblendw128 (X, Y, 1)
|
||||
#define __builtin_ia32_blendps(X, Y, M) __builtin_ia32_blendps(X, Y, 1)
|
||||
#define __builtin_ia32_blendpd(X, Y, M) __builtin_ia32_blendpd(X, Y, 1)
|
||||
#define __builtin_ia32_dpps(X, Y, M) __builtin_ia32_dpps(X, Y, 1)
|
||||
#define __builtin_ia32_dppd(X, Y, M) __builtin_ia32_dppd(X, Y, 1)
|
||||
#define __builtin_ia32_insertps128(D, S, N) __builtin_ia32_insertps128(D, S, 1)
|
||||
#define __builtin_ia32_vec_ext_v4sf(X, N) __builtin_ia32_vec_ext_v4sf(X, 1)
|
||||
#define __builtin_ia32_vec_set_v16qi(D, S, N) __builtin_ia32_vec_set_v16qi(D, S, 1)
|
||||
#define __builtin_ia32_vec_set_v4si(D, S, N) __builtin_ia32_vec_set_v4si(D, S, 1)
|
||||
#define __builtin_ia32_vec_set_v2di(D, S, N) __builtin_ia32_vec_set_v2di(D, S, 1)
|
||||
#define __builtin_ia32_vec_ext_v16qi(X, N) __builtin_ia32_vec_ext_v16qi(X, 1)
|
||||
#define __builtin_ia32_vec_ext_v4si(X, N) __builtin_ia32_vec_ext_v4si(X, 1)
|
||||
#define __builtin_ia32_vec_ext_v2di(X, N) __builtin_ia32_vec_ext_v2di(X, 1)
|
||||
#define __builtin_ia32_mpsadbw128(X, Y, M) __builtin_ia32_mpsadbw128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpistrm128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistrm128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpistri128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistri128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpestrm128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestrm128(X, LX, Y, LY, 1)
|
||||
#define __builtin_ia32_pcmpestri128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestri128(X, LX, Y, LY, 1)
|
||||
#define __builtin_ia32_pcmpistria128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistria128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpistric128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistric128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpistrio128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistrio128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpistris128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistris128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpistriz128(X, Y, M) \
|
||||
__builtin_ia32_pcmpistriz128(X, Y, 1)
|
||||
#define __builtin_ia32_pcmpestria128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestria128(X, LX, Y, LY, 1)
|
||||
#define __builtin_ia32_pcmpestric128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestric128(X, LX, Y, LY, 1)
|
||||
#define __builtin_ia32_pcmpestrio128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestrio128(X, LX, Y, LY, 1)
|
||||
#define __builtin_ia32_pcmpestris128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestris128(X, LX, Y, LY, 1)
|
||||
#define __builtin_ia32_pcmpestriz128(X, LX, Y, LY, M) \
|
||||
__builtin_ia32_pcmpestriz128(X, LX, Y, LY, 1)
|
||||
|
||||
/* tmmintrin.h */
|
||||
#define __builtin_ia32_palignr128(X, Y, N) __builtin_ia32_palignr128(X, Y, 8)
|
||||
#define __builtin_ia32_palignr(X, Y, N) __builtin_ia32_palignr(X, Y, 8)
|
||||
|
||||
/* emmintrin.h */
|
||||
#define __builtin_ia32_psrldqi128(A, B) __builtin_ia32_psrldqi128(A, 8)
|
||||
#define __builtin_ia32_pslldqi128(A, B) __builtin_ia32_pslldqi128(A, 8)
|
||||
#define __builtin_ia32_pshufhw(A, N) __builtin_ia32_pshufhw(A, 0)
|
||||
#define __builtin_ia32_pshuflw(A, N) __builtin_ia32_pshuflw(A, 0)
|
||||
#define __builtin_ia32_pshufd(A, N) __builtin_ia32_pshufd(A, 0)
|
||||
#define __builtin_ia32_vec_set_v8hi(A, D, N) \
|
||||
__builtin_ia32_vec_set_v8hi(A, D, 0)
|
||||
#define __builtin_ia32_vec_ext_v8hi(A, N) __builtin_ia32_vec_ext_v8hi(A, 0)
|
||||
#define __builtin_ia32_shufpd(A, B, N) __builtin_ia32_shufpd(A, B, 0)
|
||||
|
||||
/* xmmintrin.h */
|
||||
#define __builtin_prefetch(P, A, I) __builtin_prefetch(P, A, _MM_HINT_NTA)
|
||||
#define __builtin_ia32_pshufw(A, N) __builtin_ia32_pshufw(A, 0)
|
||||
#define __builtin_ia32_vec_set_v4hi(A, D, N) \
|
||||
__builtin_ia32_vec_set_v4hi(A, D, 0)
|
||||
#define __builtin_ia32_vec_ext_v4hi(A, N) __builtin_ia32_vec_ext_v4hi(A, 0)
|
||||
#define __builtin_ia32_shufps(A, B, N) __builtin_ia32_shufps(A, B, 0)
|
||||
|
||||
/* bmmintrin.h */
|
||||
#define __builtin_ia32_protbi(A, B) __builtin_ia32_protbi(A,1)
|
||||
#define __builtin_ia32_protwi(A, B) __builtin_ia32_protwi(A,1)
|
||||
#define __builtin_ia32_protdi(A, B) __builtin_ia32_protdi(A,1)
|
||||
#define __builtin_ia32_protqi(A, B) __builtin_ia32_protqi(A,1)
|
||||
|
||||
|
||||
#pragma GCC option ("3dnow,sse4,sse5,aes,pclmul")
|
||||
#include <wmmintrin.h>
|
||||
#include <bmmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
#include <mm3dnow.h>
|
|
@ -82,6 +82,7 @@ extern void announce_function (tree);
|
|||
extern void error_for_asm (const_rtx, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
|
||||
extern void warning_for_asm (const_rtx, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
|
||||
extern void warn_deprecated_use (tree);
|
||||
extern bool parse_optimize_options (tree, bool);
|
||||
|
||||
#ifdef BUFSIZ
|
||||
extern void output_quoted_string (FILE *, const char *);
|
||||
|
@ -158,6 +159,7 @@ extern void decode_d_option (const char *);
|
|||
|
||||
/* Return true iff flags are set as if -ffast-math. */
|
||||
extern bool fast_math_flags_set_p (void);
|
||||
extern bool fast_math_flags_struct_set_p (struct cl_optimization *);
|
||||
|
||||
/* Return log2, or -1 if not exact. */
|
||||
extern int exact_log2 (unsigned HOST_WIDE_INT);
|
||||
|
|
|
@ -3683,3 +3683,34 @@ build_duplicate_type (tree type)
|
|||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Return whether it is safe to inline a function because it used different
|
||||
target specific options or different optimization options. */
|
||||
bool
|
||||
tree_can_inline_p (tree caller, tree callee)
|
||||
{
|
||||
/* Don't inline a function with a higher optimization level than the
|
||||
caller, or with different space constraints (hot/cold functions). */
|
||||
tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (caller);
|
||||
tree callee_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee);
|
||||
|
||||
if (caller_tree != callee_tree)
|
||||
{
|
||||
struct cl_optimization *caller_opt
|
||||
= TREE_OPTIMIZATION ((caller_tree)
|
||||
? caller_tree
|
||||
: optimization_default_node);
|
||||
|
||||
struct cl_optimization *callee_opt
|
||||
= TREE_OPTIMIZATION ((callee_tree)
|
||||
? callee_tree
|
||||
: optimization_default_node);
|
||||
|
||||
if ((caller_opt->optimize > callee_opt->optimize)
|
||||
|| (caller_opt->optimize_size != callee_opt->optimize_size))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allow the backend to decide if inlining is ok. */
|
||||
return targetm.target_option.can_inline_p (caller, callee);
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@ int estimate_move_cost (tree type);
|
|||
int estimate_num_insns (tree expr, eni_weights *);
|
||||
bool tree_versionable_function_p (tree);
|
||||
void tree_function_versioning (tree, tree, varray_type, bool);
|
||||
bool tree_can_inline_p (tree, tree);
|
||||
|
||||
extern tree remap_decl (tree decl, copy_body_data *id);
|
||||
extern tree remap_type (tree type, copy_body_data *id);
|
||||
|
|
150
gcc/tree.c
150
gcc/tree.c
|
@ -175,6 +175,16 @@ static GTY (()) tree int_cst_node;
|
|||
static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
|
||||
htab_t int_cst_hash_table;
|
||||
|
||||
/* Hash table for optimization flags and target option flags. Use the same
|
||||
hash table for both sets of options. Nodes for building the current
|
||||
optimization and target option nodes. The assumption is most of the time
|
||||
the options created will already be in the hash table, so we avoid
|
||||
allocating and freeing up a node repeatably. */
|
||||
static GTY (()) tree cl_optimization_node;
|
||||
static GTY (()) tree cl_target_option_node;
|
||||
static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
|
||||
htab_t cl_option_hash_table;
|
||||
|
||||
/* General tree->tree mapping structure for use in hash tables. */
|
||||
|
||||
|
||||
|
@ -196,6 +206,8 @@ static int type_hash_eq (const void *, const void *);
|
|||
static hashval_t type_hash_hash (const void *);
|
||||
static hashval_t int_cst_hash_hash (const void *);
|
||||
static int int_cst_hash_eq (const void *, const void *);
|
||||
static hashval_t cl_option_hash_hash (const void *);
|
||||
static int cl_option_hash_eq (const void *, const void *);
|
||||
static void print_type_hash_statistics (void);
|
||||
static void print_debug_expr_statistics (void);
|
||||
static void print_value_expr_statistics (void);
|
||||
|
@ -273,6 +285,12 @@ init_ttree (void)
|
|||
|
||||
int_cst_node = make_node (INTEGER_CST);
|
||||
|
||||
cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
|
||||
cl_option_hash_eq, NULL);
|
||||
|
||||
cl_optimization_node = make_node (OPTIMIZATION_NODE);
|
||||
cl_target_option_node = make_node (TARGET_OPTION_NODE);
|
||||
|
||||
tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1;
|
||||
tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1;
|
||||
tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1;
|
||||
|
@ -505,6 +523,8 @@ tree_code_size (enum tree_code code)
|
|||
case STATEMENT_LIST: return sizeof (struct tree_statement_list);
|
||||
case BLOCK: return sizeof (struct tree_block);
|
||||
case CONSTRUCTOR: return sizeof (struct tree_constructor);
|
||||
case OPTIMIZATION_NODE: return sizeof (struct tree_optimization_option);
|
||||
case TARGET_OPTION_NODE: return sizeof (struct tree_target_option);
|
||||
|
||||
default:
|
||||
return lang_hooks.tree_size (code);
|
||||
|
@ -2427,6 +2447,8 @@ tree_node_structure (const_tree t)
|
|||
case CONSTRUCTOR: return TS_CONSTRUCTOR;
|
||||
case TREE_BINFO: return TS_BINFO;
|
||||
case OMP_CLAUSE: return TS_OMP_CLAUSE;
|
||||
case OPTIMIZATION_NODE: return TS_OPTIMIZATION;
|
||||
case TARGET_OPTION_NODE: return TS_TARGET_OPTION;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
@ -8942,4 +8964,132 @@ block_nonartificial_location (tree block)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
|
||||
nodes. */
|
||||
|
||||
/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
|
||||
|
||||
static hashval_t
|
||||
cl_option_hash_hash (const void *x)
|
||||
{
|
||||
const_tree const t = (const_tree) x;
|
||||
const char *p;
|
||||
size_t i;
|
||||
size_t len = 0;
|
||||
hashval_t hash = 0;
|
||||
|
||||
if (TREE_CODE (t) == OPTIMIZATION_NODE)
|
||||
{
|
||||
p = (const char *)TREE_OPTIMIZATION (t);
|
||||
len = sizeof (struct cl_optimization);
|
||||
}
|
||||
|
||||
else if (TREE_CODE (t) == TARGET_OPTION_NODE)
|
||||
{
|
||||
p = (const char *)TREE_TARGET_OPTION (t);
|
||||
len = sizeof (struct cl_target_option);
|
||||
}
|
||||
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
/* assume most opt flags are just 0/1, some are 2-3, and a few might be
|
||||
something else. */
|
||||
for (i = 0; i < len; i++)
|
||||
if (p[i])
|
||||
hash = (hash << 4) ^ ((i << 2) | p[i]);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Return nonzero if the value represented by *X (an OPTIMIZATION or
|
||||
TARGET_OPTION tree node) is the same as that given by *Y, which is the
|
||||
same. */
|
||||
|
||||
static int
|
||||
cl_option_hash_eq (const void *x, const void *y)
|
||||
{
|
||||
const_tree const xt = (const_tree) x;
|
||||
const_tree const yt = (const_tree) y;
|
||||
const char *xp;
|
||||
const char *yp;
|
||||
size_t len;
|
||||
|
||||
if (TREE_CODE (xt) != TREE_CODE (yt))
|
||||
return 0;
|
||||
|
||||
if (TREE_CODE (xt) == OPTIMIZATION_NODE)
|
||||
{
|
||||
xp = (const char *)TREE_OPTIMIZATION (xt);
|
||||
yp = (const char *)TREE_OPTIMIZATION (yt);
|
||||
len = sizeof (struct cl_optimization);
|
||||
}
|
||||
|
||||
else if (TREE_CODE (xt) == TARGET_OPTION_NODE)
|
||||
{
|
||||
xp = (const char *)TREE_TARGET_OPTION (xt);
|
||||
yp = (const char *)TREE_TARGET_OPTION (yt);
|
||||
len = sizeof (struct cl_target_option);
|
||||
}
|
||||
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
return (memcmp (xp, yp, len) == 0);
|
||||
}
|
||||
|
||||
/* Build an OPTIMIZATION_NODE based on the current options. */
|
||||
|
||||
tree
|
||||
build_optimization_node (void)
|
||||
{
|
||||
tree t;
|
||||
void **slot;
|
||||
|
||||
/* Use the cache of optimization nodes. */
|
||||
|
||||
cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node));
|
||||
|
||||
slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
|
||||
t = (tree) *slot;
|
||||
if (!t)
|
||||
{
|
||||
/* Insert this one into the hash table. */
|
||||
t = cl_optimization_node;
|
||||
*slot = t;
|
||||
|
||||
/* Make a new node for next time round. */
|
||||
cl_optimization_node = make_node (OPTIMIZATION_NODE);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Build a TARGET_OPTION_NODE based on the current options. */
|
||||
|
||||
tree
|
||||
build_target_option_node (void)
|
||||
{
|
||||
tree t;
|
||||
void **slot;
|
||||
|
||||
/* Use the cache of optimization nodes. */
|
||||
|
||||
cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node));
|
||||
|
||||
slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
|
||||
t = (tree) *slot;
|
||||
if (!t)
|
||||
{
|
||||
/* Insert this one into the hash table. */
|
||||
t = cl_target_option_node;
|
||||
*slot = t;
|
||||
|
||||
/* Make a new node for next time round. */
|
||||
cl_target_option_node = make_node (TARGET_OPTION_NODE);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#include "gt-tree.h"
|
||||
|
|
|
@ -1194,6 +1194,13 @@ DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "vec_interleavelow_expr", tcc_binary, 2)
|
|||
all conditional branches leading to execution paths executing the
|
||||
PREDICT_EXPR will get predicted by the specified predictor. */
|
||||
DEFTREECODE (PREDICT_EXPR, "predict_expr", tcc_unary, 1)
|
||||
|
||||
/* OPTIMIZATION_NODE. Node to store the optimization options. */
|
||||
DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
|
||||
|
||||
/* TARGET_OPTION_NODE. Node to store the target specific options. */
|
||||
DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0)
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
mode:c
|
||||
|
|
75
gcc/tree.h
75
gcc/tree.h
|
@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "vec.h"
|
||||
#include "double-int.h"
|
||||
#include "alias.h"
|
||||
#include "options.h"
|
||||
|
||||
/* Codes of tree nodes */
|
||||
|
||||
|
@ -3408,6 +3409,16 @@ struct tree_decl_non_common GTY(())
|
|||
#define DECL_ARGUMENTS(NODE) (FUNCTION_DECL_CHECK (NODE)->decl_non_common.arguments)
|
||||
#define DECL_ARGUMENT_FLD(NODE) (DECL_NON_COMMON_CHECK (NODE)->decl_non_common.arguments)
|
||||
|
||||
/* In FUNCTION_DECL, the function specific target options to use when compiling
|
||||
this function. */
|
||||
#define DECL_FUNCTION_SPECIFIC_TARGET(NODE) \
|
||||
(FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_target)
|
||||
|
||||
/* In FUNCTION_DECL, the function specific optimization options to use when
|
||||
compiling this function. */
|
||||
#define DECL_FUNCTION_SPECIFIC_OPTIMIZATION(NODE) \
|
||||
(FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_optimization)
|
||||
|
||||
/* FUNCTION_DECL inherits from DECL_NON_COMMON because of the use of the
|
||||
arguments/result/saved_tree fields by front ends. It was either inherit
|
||||
FUNCTION_DECL from non_common, or inherit non_common from FUNCTION_DECL,
|
||||
|
@ -3419,6 +3430,10 @@ struct tree_function_decl GTY(())
|
|||
|
||||
struct function *f;
|
||||
|
||||
/* Function specific options that are used by this function. */
|
||||
tree function_specific_target; /* target options */
|
||||
tree function_specific_optimization; /* optimization options */
|
||||
|
||||
/* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
|
||||
DECL_FUNCTION_CODE. Otherwise unused.
|
||||
??? The bitfield needs to be able to hold all target function
|
||||
|
@ -3491,6 +3506,39 @@ struct tree_statement_list
|
|||
struct tree_statement_list_node *tail;
|
||||
};
|
||||
|
||||
|
||||
/* Optimization options used by a function. */
|
||||
|
||||
struct tree_optimization_option GTY(())
|
||||
{
|
||||
struct tree_common common;
|
||||
|
||||
/* The optimization options used by the user. */
|
||||
struct cl_optimization opts;
|
||||
};
|
||||
|
||||
#define TREE_OPTIMIZATION(NODE) \
|
||||
(&OPTIMIZATION_NODE_CHECK (NODE)->optimization.opts)
|
||||
|
||||
/* Return a tree node that encapsulates the current optimization options. */
|
||||
extern tree build_optimization_node (void);
|
||||
|
||||
/* Target options used by a function. */
|
||||
|
||||
struct tree_target_option GTY(())
|
||||
{
|
||||
struct tree_common common;
|
||||
|
||||
/* The optimization options used by the user. */
|
||||
struct cl_target_option opts;
|
||||
};
|
||||
|
||||
#define TREE_TARGET_OPTION(NODE) \
|
||||
(&TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts)
|
||||
|
||||
/* Return a tree node that encapsulates the current target options. */
|
||||
extern tree build_target_option_node (void);
|
||||
|
||||
|
||||
/* Define the overall contents of a tree node.
|
||||
It may be any of the structures declared above
|
||||
|
@ -3535,6 +3583,8 @@ union tree_node GTY ((ptr_alias (union lang_tree_node),
|
|||
struct tree_memory_tag GTY ((tag ("TS_MEMORY_TAG"))) mtag;
|
||||
struct tree_omp_clause GTY ((tag ("TS_OMP_CLAUSE"))) omp_clause;
|
||||
struct tree_memory_partition_tag GTY ((tag ("TS_MEMORY_PARTITION_TAG"))) mpt;
|
||||
struct tree_optimization_option GTY ((tag ("TS_OPTIMIZATION"))) optimization;
|
||||
struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
|
||||
};
|
||||
|
||||
/* Standard named or nameless data types of the C compiler. */
|
||||
|
@ -3682,6 +3732,15 @@ enum tree_index
|
|||
TI_SAT_UDA_TYPE,
|
||||
TI_SAT_UTA_TYPE,
|
||||
|
||||
TI_OPTIMIZATION_DEFAULT,
|
||||
TI_OPTIMIZATION_CURRENT,
|
||||
TI_OPTIMIZATION_COLD,
|
||||
TI_OPTIMIZATION_HOT,
|
||||
TI_TARGET_OPTION_DEFAULT,
|
||||
TI_TARGET_OPTION_CURRENT,
|
||||
TI_CURRENT_OPTION_PRAGMA,
|
||||
TI_CURRENT_OPTIMIZE_PRAGMA,
|
||||
|
||||
TI_MAX
|
||||
};
|
||||
|
||||
|
@ -3849,6 +3908,22 @@ extern GTY(()) tree global_trees[TI_MAX];
|
|||
#define main_identifier_node global_trees[TI_MAIN_IDENTIFIER]
|
||||
#define MAIN_NAME_P(NODE) (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node)
|
||||
|
||||
/* Optimization options (OPTIMIZATION_NODE) to use for default, current, cold,
|
||||
and hot functions. */
|
||||
#define optimization_default_node global_trees[TI_OPTIMIZATION_DEFAULT]
|
||||
#define optimization_current_node global_trees[TI_OPTIMIZATION_CURRENT]
|
||||
#define optimization_cold_node global_trees[TI_OPTIMIZATION_COLD]
|
||||
#define optimization_hot_node global_trees[TI_OPTIMIZATION_HOT]
|
||||
|
||||
/* Default/current target options (TARGET_OPTION_NODE). */
|
||||
#define target_option_default_node global_trees[TI_TARGET_OPTION_DEFAULT]
|
||||
#define target_option_current_node global_trees[TI_TARGET_OPTION_CURRENT]
|
||||
|
||||
/* Default tree list option(), optimize() pragmas to be linked into the
|
||||
attribute list. */
|
||||
#define current_option_pragma global_trees[TI_CURRENT_OPTION_PRAGMA]
|
||||
#define current_optimize_pragma global_trees[TI_CURRENT_OPTIMIZE_PRAGMA]
|
||||
|
||||
/* An enumeration of the standard C integer types. These must be
|
||||
ordered so that shorter types appear before longer ones, and so
|
||||
that signed types appear before unsigned ones, for the correct
|
||||
|
|
|
@ -63,3 +63,6 @@ DEFTREESTRUCT(TS_CONSTRUCTOR, "constructor")
|
|||
DEFTREESTRUCT(TS_MEMORY_TAG, "memory tag")
|
||||
DEFTREESTRUCT(TS_OMP_CLAUSE, "omp clause")
|
||||
DEFTREESTRUCT(TS_MEMORY_PARTITION_TAG, "memory partition tag")
|
||||
DEFTREESTRUCT(TS_OPTIMIZATION, "optimization options")
|
||||
DEFTREESTRUCT(TS_TARGET_OPTION, "target options")
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue