aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@linaro.org>2016-04-11 15:20:14 +0200
committerLinaro Code Review <review@review.linaro.org>2016-04-12 10:59:45 +0000
commit55d3bceea8eef018564a026e615af58cca5d6273 (patch)
treecd5fae31de16d725f1b590dfa176a0c5e2b26877
parent07017c3304ec630a4d2b63fdf6346be9407f9153 (diff)
gcc/
Backport from trunk r233342. 2016-02-11 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/aarch64/aarch64.c (aarch64_last_printed_arch_string): New variable. (aarch64_last_printed_tune_string): Likewise. (aarch64_declare_function_name): Only output .arch assembler directive if it will be different from the previously output directive. Same for .tune comment but only if -dA is set. (aarch64_start_file): New function. (TARGET_ASM_FILE_START): Define. gcc/testsuite/ Backport from trunk r233342. 2016-02-11 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * gcc.target/aarch64/target_attr_15.c: Scan assembly for .arch armv8-a\n. Add -dA to dg-options. * gcc.target/aarch64/assembler_arch_1.c: New test. * gcc.target/aarch64/target_attr_7.c: Add -dA to dg-options. gcc/testsuite/ Backport from trunk r233559. 2016-02-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * lib/target-supports.exp: Define aarch64_asm_FUNC_ok checks for fp, simd, crypto, crc, lse. * doc/sourcebuild.texi (AArch64-specific attributes): Document the above. * gcc.target/aarch64/assembler_arch_1.c: Add aarch64_asm_lse_ok effective target check. gcc/ Backport from trunk r234875. 2016-04-11 James Greenhalgh <james.greenhalgh@arm.com> * config/aarch64/aarch64.h (AARCH64_FL_FOR_ARCH8_1): Also add AARCH64_FL_CRC. gcc/ Backport from trunk r234876. 2016-04-11 James Greenhalgh <james.greenhalgh@arm.com> PR target/70133 * config/aarch64/aarch64-common.c (aarch64_option_extension): Keep track of a canonical flag name. (all_extensions): Likewise. (arch_to_arch_name): Also track extension flags enabled by the arch. (all_architectures): Likewise. (aarch64_parse_extension): Move to here. (aarch64_get_extension_string_for_isa_flags): Take a new argument, rework. (aarch64_rewrite_selected_cpu): Update for above change. * config/aarch64/aarch64-option-extensions.def: Rework the way flags are handled, such that the single explicit value enabled by an extension is kept seperate from the implicit values it also enables. * config/aarch64/aarch64-protos.h (aarch64_parse_opt_result): Move to here. (aarch64_parse_extension): New. * config/aarch64/aarch64.c (aarch64_parse_opt_result): Move from here to config/aarch64/aarch64-protos.h. (aarch64_parse_extension): Move from here to common/config/aarch64/aarch64-common.c. (aarch64_option_print): Update. (aarch64_declare_function_name): Likewise. (aarch64_start_file): Likewise. * config/aarch64/driver-aarch64.c (arch_extension): Keep track of the canonical flag for extensions. * config.gcc (aarch64*-*-*): Extend regex for capturing extension flags. gcc/testsuite/ Backport from trunk r234876. 2016-04-11 James Greenhalgh <james.greenhalgh@arm.com> PR target/70133 * gcc.target/aarch64/mgeneral-regs_4.c: Fix expected output. * gcc.target/aarch64/target_attr_15.c: Likewise. gcc/ Backport from trunk r234877. 2016-04-11 James Greenhalgh <james.greenhalgh@arm.com> PR target/70133 * config/aarch64/driver-aarch64.c (aarch64_get_extension_string_for_isa_flags): New. (arch_extension): Rename to... (aarch64_arch_extension): ...This. (ext_to_feat_string): Rename to... (aarch64_extensions): ...This. (aarch64_core_data): Keep track of architecture extension flags. (cpu_data): Rename to... (aarch64_cpu_data): ...This. (aarch64_arch_driver_info): Keep track of architecture extension flags. (get_arch_name_from_id): Rename to... (get_arch_from_id): ...This, change return type. (host_detect_local_cpu): Update and reformat for renames, handle extensions through common infrastructure. Change-Id: I30437869d04438f2efc2946e6bdfc5a621578cce
-rw-r--r--gcc/common/config/aarch64/aarch64-common.c116
-rw-r--r--gcc/config.gcc14
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def36
-rw-r--r--gcc/config/aarch64/aarch64-protos.h26
-rw-r--r--gcc/config/aarch64/aarch64.c136
-rw-r--r--gcc/config/aarch64/aarch64.h2
-rw-r--r--gcc/config/aarch64/driver-aarch64.c192
-rw-r--r--gcc/doc/sourcebuild.texi3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/assembler_arch_1.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/target_attr_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/target_attr_15.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/target_attr_7.c2
-rw-r--r--gcc/testsuite/lib/target-supports.exp17
14 files changed, 369 insertions, 204 deletions
diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c
index 07c6bba4519..ae34dfa95a1 100644
--- a/gcc/common/config/aarch64/aarch64-common.c
+++ b/gcc/common/config/aarch64/aarch64-common.c
@@ -111,6 +111,7 @@ struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
struct aarch64_option_extension
{
const char *const name;
+ const unsigned long flag_canonical;
const unsigned long flags_on;
const unsigned long flags_off;
};
@@ -118,11 +119,11 @@ struct aarch64_option_extension
/* ISA extensions in AArch64. */
static const struct aarch64_option_extension all_extensions[] =
{
-#define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
- {NAME, FLAGS_ON, FLAGS_OFF},
+#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \
+ {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF},
#include "config/aarch64/aarch64-option-extensions.def"
#undef AARCH64_OPT_EXTENSION
- {NULL, 0, 0}
+ {NULL, 0, 0, 0}
};
struct processor_name_to_arch
@@ -136,6 +137,7 @@ struct arch_to_arch_name
{
const enum aarch64_arch arch;
const std::string arch_name;
+ const unsigned long flags;
};
/* Map processor names to the architecture revision they implement and
@@ -154,26 +156,111 @@ static const struct processor_name_to_arch all_cores[] =
static const struct arch_to_arch_name all_architectures[] =
{
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \
- {AARCH64_ARCH_##ARCH_IDENT, NAME},
+ {AARCH64_ARCH_##ARCH_IDENT, NAME, FLAGS},
#include "config/aarch64/aarch64-arches.def"
#undef AARCH64_ARCH
- {aarch64_no_arch, ""}
+ {aarch64_no_arch, "", 0}
};
-/* Return a string representation of ISA_FLAGS. */
+/* Parse the architecture extension string STR and update ISA_FLAGS
+ with the architecture features turned on or off. Return a
+ aarch64_parse_opt_result describing the result. */
+
+enum aarch64_parse_opt_result
+aarch64_parse_extension (const char *str, unsigned long *isa_flags)
+{
+ /* The extension string is parsed left to right. */
+ const struct aarch64_option_extension *opt = NULL;
+
+ /* Flag to say whether we are adding or removing an extension. */
+ int adding_ext = -1;
+
+ while (str != NULL && *str != 0)
+ {
+ const char *ext;
+ size_t len;
+
+ str++;
+ ext = strchr (str, '+');
+
+ if (ext != NULL)
+ len = ext - str;
+ else
+ len = strlen (str);
+
+ if (len >= 2 && strncmp (str, "no", 2) == 0)
+ {
+ adding_ext = 0;
+ len -= 2;
+ str += 2;
+ }
+ else if (len > 0)
+ adding_ext = 1;
+
+ if (len == 0)
+ return AARCH64_PARSE_MISSING_ARG;
+
+
+ /* Scan over the extensions table trying to find an exact match. */
+ for (opt = all_extensions; opt->name != NULL; opt++)
+ {
+ if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0)
+ {
+ /* Add or remove the extension. */
+ if (adding_ext)
+ *isa_flags |= (opt->flags_on | opt->flag_canonical);
+ else
+ *isa_flags &= ~(opt->flags_off | opt->flag_canonical);
+ break;
+ }
+ }
+
+ if (opt->name == NULL)
+ {
+ /* Extension not found in list. */
+ return AARCH64_PARSE_INVALID_FEATURE;
+ }
+
+ str = ext;
+ };
+
+ return AARCH64_PARSE_OK;
+}
+
+/* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
+ gives the default set of flags which are implied by whatever -march
+ we'd put out. Our job is to figure out the minimal set of "+" and
+ "+no" feature flags to put out, and to put them out grouped such
+ that all the "+" flags come before the "+no" flags. */
std::string
-aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags)
+aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags,
+ unsigned long default_arch_flags)
{
const struct aarch64_option_extension *opt = NULL;
std::string outstr = "";
+ /* Pass one: Find all the things we need to turn on. As a special case,
+ we always want to put out +crc if it is enabled. */
for (opt = all_extensions; opt->name != NULL; opt++)
- if ((isa_flags & opt->flags_on) == opt->flags_on)
+ if ((isa_flags & opt->flag_canonical
+ && !(default_arch_flags & opt->flag_canonical))
+ || (default_arch_flags & opt->flag_canonical
+ && opt->flag_canonical == AARCH64_ISA_CRC))
{
outstr += "+";
outstr += opt->name;
}
+
+ /* Pass two: Find all the things we need to turn off. */
+ for (opt = all_extensions; opt->name != NULL; opt++)
+ if ((~isa_flags) & opt->flag_canonical
+ && !((~default_arch_flags) & opt->flag_canonical))
+ {
+ outstr += "+no";
+ outstr += opt->name;
+ }
+
return outstr;
}
@@ -185,7 +272,7 @@ const char *
aarch64_rewrite_selected_cpu (const char *name)
{
std::string original_string (name);
- std::string extensions;
+ std::string extension_str;
std::string processor;
size_t extension_pos = original_string.find_first_of ('+');
@@ -193,8 +280,8 @@ aarch64_rewrite_selected_cpu (const char *name)
if (extension_pos != std::string::npos)
{
processor = original_string.substr (0, extension_pos);
- extensions = original_string.substr (extension_pos,
- std::string::npos);
+ extension_str = original_string.substr (extension_pos,
+ std::string::npos);
}
else
{
@@ -226,9 +313,12 @@ aarch64_rewrite_selected_cpu (const char *name)
|| a_to_an->arch == aarch64_no_arch)
fatal_error (input_location, "unknown value %qs for -mcpu", name);
+ unsigned long extensions = p_to_a->flags;
+ aarch64_parse_extension (extension_str.c_str (), &extensions);
+
std::string outstr = a_to_an->arch_name
- + aarch64_get_extension_string_for_isa_flags (p_to_a->flags)
- + extensions;
+ + aarch64_get_extension_string_for_isa_flags (extensions,
+ a_to_an->flags);
/* We are going to memory leak here, nobody elsewhere
in the callchain is going to clean up after us. The alternative is
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 1c547a02035..9c24db2bf43 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3536,22 +3536,28 @@ case "${target}" in
${srcdir}/config/aarch64/aarch64-option-extensions.def \
> /dev/null; then
- ext_on=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
+ ext_canon=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
${srcdir}/config/aarch64/aarch64-option-extensions.def | \
sed -e 's/^[^,]*,[ ]*//' | \
sed -e 's/,.*$//'`
- ext_off=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
+ ext_on=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
${srcdir}/config/aarch64/aarch64-option-extensions.def | \
sed -e 's/^[^,]*,[ ]*[^,]*,[ ]*//' | \
sed -e 's/,.*$//' | \
sed -e 's/).*$//'`
+ ext_off=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
+ ${srcdir}/config/aarch64/aarch64-option-extensions.def | \
+ sed -e 's/^[^,]*,[ ]*[^,]*,[ ]*[^,]*,[ ]*//' | \
+ sed -e 's/,.*$//' | \
+ sed -e 's/).*$//'`
+
if [ $ext = $base_ext ]; then
# Adding extension
- ext_mask="("$ext_mask") | ("$ext_on")"
+ ext_mask="("$ext_mask") | ("$ext_on" | "$ext_canon")"
else
# Removing extension
- ext_mask="("$ext_mask") & ~("$ext_off")"
+ ext_mask="("$ext_mask") & ~("$ext_off" | "$ext_canon")"
fi
true
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index 3e94c313690..520f2952eb5 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -21,23 +21,37 @@
Before using #include to read this file, define a macro:
- AARCH64_OPT_EXTENSION(EXT_NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING)
+ AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, FEATURE_STRING)
EXT_NAME is the name of the extension, represented as a string constant.
- FLAGS_ON are the bitwise-or of the features that the extension adds.
- FLAGS_OFF are the bitwise-or of the features that the extension removes.
+ FLAGS_CANONICAL is the canonical internal name for this flag.
+ FLAGS_ON are the bitwise-or of the features that enabling the extension
+ adds, or zero if enabling this extension has no effect on other features.
+ FLAGS_OFF are the bitwise-or of the features that disabling the extension
+ removes, or zero if disabling this extension has no effect on other
+ features.
FEAT_STRING is a string containing the entries in the 'Features' field of
/proc/cpuinfo on a GNU/Linux system that correspond to this architecture
extension being available. Sometimes multiple entries are needed to enable
the extension (for example, the 'crypto' extension depends on four
entries: aes, pmull, sha1, sha2 being present). In that case this field
- should contain a whitespace-separated list of the strings in 'Features'
+ should contain a space (" ") separated list of the strings in 'Features'
that are required. Their order is not important. */
-AARCH64_OPT_EXTENSION ("fp", AARCH64_FL_FP,
- AARCH64_FL_FPSIMD | AARCH64_FL_CRYPTO, "fp")
-AARCH64_OPT_EXTENSION ("simd", AARCH64_FL_FPSIMD,
- AARCH64_FL_SIMD | AARCH64_FL_CRYPTO, "asimd")
-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO | AARCH64_FL_FPSIMD, AARCH64_FL_CRYPTO, "aes pmull sha1 sha2")
-AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, AARCH64_FL_CRC, "crc32")
-AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, AARCH64_FL_LSE, "atomics")
+/* Enabling "fp" just enables "fp".
+ Disabling "fp" also disables "simd", "crypto". */
+AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO, "fp")
+
+/* Enabling "simd" also enables "fp".
+ Disabling "simd" also disables "crypto". */
+AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO, "asimd")
+
+/* Enabling "crypto" also enables "fp", "simd".
+ Disabling "crypto" just disables "crypto". */
+AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, "aes pmull sha1 sha2")
+
+/* Enabling or disabling "crc" only changes "crc". */
+AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, "crc32")
+
+/* Enabling or disabling "lse" only changes "lse". */
+AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, "atomics")
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index e85132f484a..9bf433594c5 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -262,6 +262,18 @@ enum aarch64_extra_tuning_flags
};
#undef AARCH64_EXTRA_TUNING_OPTION
+/* Enum describing the various ways that the
+ aarch64_parse_{arch,tune,cpu,extension} functions can fail.
+ This way their callers can choose what kind of error to give. */
+
+enum aarch64_parse_opt_result
+{
+ AARCH64_PARSE_OK, /* Parsing was successful. */
+ AARCH64_PARSE_MISSING_ARG, /* Missing argument. */
+ AARCH64_PARSE_INVALID_FEATURE, /* Invalid feature modifier. */
+ AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
+};
+
extern struct tune_params aarch64_tune_params;
HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
@@ -279,8 +291,6 @@ bool aarch64_float_const_zero_rtx_p (rtx);
bool aarch64_function_arg_regno_p (unsigned);
bool aarch64_gen_movmemqi (rtx *);
bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
-bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
- const struct cl_decoded_option *, location_t);
bool aarch64_is_extend_from_extract (machine_mode, rtx, rtx);
bool aarch64_is_long_call_p (rtx);
bool aarch64_is_noplt_call_p (rtx);
@@ -314,7 +324,6 @@ bool aarch64_uimm12_shift (HOST_WIDE_INT);
bool aarch64_use_return_insn_p (void);
const char *aarch64_mangle_builtin_type (const_tree);
const char *aarch64_output_casesi (rtx *);
-const char *aarch64_rewrite_selected_cpu (const char *name);
enum aarch64_symbol_type aarch64_classify_symbol (rtx, rtx);
enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
@@ -335,7 +344,6 @@ rtx aarch64_simd_gen_const_vector_dup (machine_mode, int);
bool aarch64_simd_mem_operand_p (rtx);
rtx aarch64_simd_vect_par_cnst_half (machine_mode, bool);
rtx aarch64_tls_get_addr (void);
-std::string aarch64_get_extension_string_for_isa_flags (unsigned long);
tree aarch64_fold_builtin (tree, int, tree *, bool);
unsigned aarch64_dbx_register_number (unsigned);
unsigned aarch64_trampoline_size (void);
@@ -428,4 +436,14 @@ bool extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset);
bool aarch64_operands_ok_for_ldpstp (rtx *, bool, enum machine_mode);
bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, enum machine_mode);
extern bool aarch64_nopcrelative_literal_loads;
+
+/* Defined in common/config/aarch64-common.c. */
+bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
+ const struct cl_decoded_option *, location_t);
+const char *aarch64_rewrite_selected_cpu (const char *name);
+enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
+ unsigned long *);
+std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
+ unsigned long);
+
#endif /* GCC_AARCH64_PROTOS_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 47f41ab2197..1a20ed2a525 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -629,7 +629,7 @@ struct aarch64_option_extension
/* ISA extensions in AArch64. */
static const struct aarch64_option_extension all_extensions[] =
{
-#define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
+#define AARCH64_OPT_EXTENSION(NAME, X, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
{NAME, FLAGS_ON, FLAGS_OFF},
#include "aarch64-option-extensions.def"
#undef AARCH64_OPT_EXTENSION
@@ -7293,83 +7293,6 @@ aarch64_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
static void initialize_aarch64_code_model (struct gcc_options *);
-/* Enum describing the various ways that the
- aarch64_parse_{arch,tune,cpu,extension} functions can fail.
- This way their callers can choose what kind of error to give. */
-
-enum aarch64_parse_opt_result
-{
- AARCH64_PARSE_OK, /* Parsing was successful. */
- AARCH64_PARSE_MISSING_ARG, /* Missing argument. */
- AARCH64_PARSE_INVALID_FEATURE, /* Invalid feature modifier. */
- AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
-};
-
-/* Parse the architecture extension string STR and update ISA_FLAGS
- with the architecture features turned on or off. Return a
- aarch64_parse_opt_result describing the result. */
-
-static enum aarch64_parse_opt_result
-aarch64_parse_extension (char *str, unsigned long *isa_flags)
-{
- /* The extension string is parsed left to right. */
- const struct aarch64_option_extension *opt = NULL;
-
- /* Flag to say whether we are adding or removing an extension. */
- int adding_ext = -1;
-
- while (str != NULL && *str != 0)
- {
- char *ext;
- size_t len;
-
- str++;
- ext = strchr (str, '+');
-
- if (ext != NULL)
- len = ext - str;
- else
- len = strlen (str);
-
- if (len >= 2 && strncmp (str, "no", 2) == 0)
- {
- adding_ext = 0;
- len -= 2;
- str += 2;
- }
- else if (len > 0)
- adding_ext = 1;
-
- if (len == 0)
- return AARCH64_PARSE_MISSING_ARG;
-
-
- /* Scan over the extensions table trying to find an exact match. */
- for (opt = all_extensions; opt->name != NULL; opt++)
- {
- if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0)
- {
- /* Add or remove the extension. */
- if (adding_ext)
- *isa_flags |= opt->flags_on;
- else
- *isa_flags &= ~(opt->flags_off);
- break;
- }
- }
-
- if (opt->name == NULL)
- {
- /* Extension not found in list. */
- return AARCH64_PARSE_INVALID_FEATURE;
- }
-
- str = ext;
- };
-
- return AARCH64_PARSE_OK;
-}
-
/* Parse the TO_PARSE string and put the architecture struct that it
selects into RES and the architectural features into ISA_FLAGS.
Return an aarch64_parse_opt_result describing the parse result.
@@ -8155,7 +8078,7 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
unsigned long isa_flags = ptr->x_aarch64_isa_flags;
const struct processor *arch = aarch64_get_arch (ptr->x_explicit_arch);
std::string extension
- = aarch64_get_extension_string_for_isa_flags (isa_flags);
+ = aarch64_get_extension_string_for_isa_flags (isa_flags, arch->flags);
fprintf (file, "%*sselected tune = %s\n", indent, "", cpu->name);
fprintf (file, "%*sselected arch = %s%s\n", indent, "",
@@ -10842,6 +10765,10 @@ aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
}
+/* The last .arch and .tune assembly strings that we printed. */
+static std::string aarch64_last_printed_arch_string;
+static std::string aarch64_last_printed_tune_string;
+
/* Implement ASM_DECLARE_FUNCTION_NAME. Output the ISA features used
by the function fndecl. */
@@ -10863,24 +10790,58 @@ aarch64_declare_function_name (FILE *stream, const char* name,
unsigned long isa_flags = targ_options->x_aarch64_isa_flags;
std::string extension
- = aarch64_get_extension_string_for_isa_flags (isa_flags);
- asm_fprintf (asm_out_file, "\t.arch %s%s\n",
- this_arch->name, extension.c_str ());
+ = aarch64_get_extension_string_for_isa_flags (isa_flags,
+ this_arch->flags);
+ /* Only update the assembler .arch string if it is distinct from the last
+ such string we printed. */
+ std::string to_print = this_arch->name + extension;
+ if (to_print != aarch64_last_printed_arch_string)
+ {
+ asm_fprintf (asm_out_file, "\t.arch %s\n", to_print.c_str ());
+ aarch64_last_printed_arch_string = to_print;
+ }
/* Print the cpu name we're tuning for in the comments, might be
- useful to readers of the generated asm. */
-
+ useful to readers of the generated asm. Do it only when it changes
+ from function to function and verbose assembly is requested. */
const struct processor *this_tune
= aarch64_get_tune_cpu (targ_options->x_explicit_tune_core);
- asm_fprintf (asm_out_file, "\t" ASM_COMMENT_START ".tune %s\n",
- this_tune->name);
+ if (flag_debug_asm && aarch64_last_printed_tune_string != this_tune->name)
+ {
+ asm_fprintf (asm_out_file, "\t" ASM_COMMENT_START ".tune %s\n",
+ this_tune->name);
+ aarch64_last_printed_tune_string = this_tune->name;
+ }
/* Don't forget the type directive for ELF. */
ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function");
ASM_OUTPUT_LABEL (stream, name);
}
+/* Implements TARGET_ASM_FILE_START. Output the assembly header. */
+
+static void
+aarch64_start_file (void)
+{
+ struct cl_target_option *default_options
+ = TREE_TARGET_OPTION (target_option_default_node);
+
+ const struct processor *default_arch
+ = aarch64_get_arch (default_options->x_explicit_arch);
+ unsigned long default_isa_flags = default_options->x_aarch64_isa_flags;
+ std::string extension
+ = aarch64_get_extension_string_for_isa_flags (default_isa_flags,
+ default_arch->flags);
+
+ aarch64_last_printed_arch_string = default_arch->name + extension;
+ aarch64_last_printed_tune_string = "";
+ asm_fprintf (asm_out_file, "\t.arch %s\n",
+ aarch64_last_printed_arch_string.c_str ());
+
+ default_file_start ();
+}
+
/* Emit load exclusive. */
static void
@@ -13579,6 +13540,9 @@ aarch64_unspec_may_trap_p (const_rtx x, unsigned flags)
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
hook_bool_const_tree_hwi_hwi_const_tree_true
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START aarch64_start_file
+
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK aarch64_output_mi_thunk
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 10506a79d8e..759e6a2934e 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -147,7 +147,7 @@ extern unsigned aarch64_architecture_version;
/* Architecture flags that effect instruction selection. */
#define AARCH64_FL_FOR_ARCH8 (AARCH64_FL_FPSIMD)
#define AARCH64_FL_FOR_ARCH8_1 \
- (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_V8_1)
+ (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC | AARCH64_FL_V8_1)
/* Macros to test ISA flags. */
diff --git a/gcc/config/aarch64/driver-aarch64.c b/gcc/config/aarch64/driver-aarch64.c
index ae4d5a00ec5..e51b083034a 100644
--- a/gcc/config/aarch64/driver-aarch64.c
+++ b/gcc/config/aarch64/driver-aarch64.c
@@ -18,17 +18,25 @@
<http://www.gnu.org/licenses/>. */
#include "config.h"
+#define INCLUDE_STRING
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
-struct arch_extension
+/* Defined in common/config/aarch64/aarch64-common.c. */
+std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
+ unsigned long);
+
+struct aarch64_arch_extension
{
const char *ext;
+ unsigned int flag;
const char *feat_string;
};
-#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
- { EXT_NAME, FEATURE_STRING },
-static struct arch_extension ext_to_feat_string[] =
+#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
+ { EXT_NAME, FLAG_CANONICAL, FEATURE_STRING },
+static struct aarch64_arch_extension aarch64_extensions[] =
{
#include "aarch64-option-extensions.def"
};
@@ -41,15 +49,16 @@ struct aarch64_core_data
const char* arch;
const char* implementer_id;
const char* part_no;
+ const unsigned long flags;
};
#define AARCH64_CORE(CORE_NAME, CORE_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART) \
- { CORE_NAME, #ARCH, IMP, PART },
+ { CORE_NAME, #ARCH, IMP, PART, FLAGS },
-static struct aarch64_core_data cpu_data [] =
+static struct aarch64_core_data aarch64_cpu_data[] =
{
#include "aarch64-cores.def"
- { NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, 0 }
};
#undef AARCH64_CORE
@@ -58,37 +67,37 @@ struct aarch64_arch_driver_info
{
const char* id;
const char* name;
+ const unsigned long flags;
};
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
- { #ARCH_IDENT, NAME },
+ { #ARCH_IDENT, NAME, FLAGS },
-static struct aarch64_arch_driver_info aarch64_arches [] =
+static struct aarch64_arch_driver_info aarch64_arches[] =
{
#include "aarch64-arches.def"
- {NULL, NULL}
+ {NULL, NULL, 0}
};
#undef AARCH64_ARCH
-/* Return the full architecture name string corresponding to the
- identifier ID. */
+/* Return an aarch64_arch_driver_info for the architecture described
+ by ID, or NULL if ID describes something we don't know about. */
-static const char*
-get_arch_name_from_id (const char* id)
+static struct aarch64_arch_driver_info*
+get_arch_from_id (const char* id)
{
unsigned int i = 0;
for (i = 0; aarch64_arches[i].id != NULL; i++)
{
if (strcmp (id, aarch64_arches[i].id) == 0)
- return aarch64_arches[i].name;
+ return &aarch64_arches[i];
}
return NULL;
}
-
/* Check wether the string CORE contains the same CPU part numbers
as BL_STRING. For example CORE="{0xd03, 0xd07}" and BL_STRING="0xd07.0xd03"
should return true. */
@@ -97,7 +106,7 @@ static bool
valid_bL_string_p (const char** core, const char* bL_string)
{
return strstr (bL_string, core[0]) != NULL
- && strstr (bL_string, core[1]) != NULL;
+ && strstr (bL_string, core[1]) != NULL;
}
/* Return true iff ARR contains STR in one of its two elements. */
@@ -141,7 +150,7 @@ host_detect_local_cpu (int argc, const char **argv)
{
const char *arch_id = NULL;
const char *res = NULL;
- static const int num_exts = ARRAY_SIZE (ext_to_feat_string);
+ static const int num_exts = ARRAY_SIZE (aarch64_extensions);
char buf[128];
FILE *f = NULL;
bool arch = false;
@@ -155,6 +164,8 @@ host_detect_local_cpu (int argc, const char **argv)
unsigned int n_imps = 0;
bool processed_exts = false;
const char *ext_string = "";
+ unsigned long extension_flags = 0;
+ unsigned long default_flags = 0;
gcc_assert (argc);
@@ -183,60 +194,71 @@ host_detect_local_cpu (int argc, const char **argv)
{
if (strstr (buf, "implementer") != NULL)
{
- for (i = 0; cpu_data[i].name != NULL; i++)
- if (strstr (buf, cpu_data[i].implementer_id) != NULL
- && !contains_string_p (imps, cpu_data[i].implementer_id))
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ if (strstr (buf, aarch64_cpu_data[i].implementer_id) != NULL
+ && !contains_string_p (imps,
+ aarch64_cpu_data[i].implementer_id))
{
- if (n_imps == 2)
- goto not_found;
+ if (n_imps == 2)
+ goto not_found;
- imps[n_imps++] = cpu_data[i].implementer_id;
+ imps[n_imps++] = aarch64_cpu_data[i].implementer_id;
- break;
+ break;
}
- continue;
+ continue;
}
if (strstr (buf, "part") != NULL)
{
- for (i = 0; cpu_data[i].name != NULL; i++)
- if (strstr (buf, cpu_data[i].part_no) != NULL
- && !contains_string_p (cores, cpu_data[i].part_no))
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ if (strstr (buf, aarch64_cpu_data[i].part_no) != NULL
+ && !contains_string_p (cores, aarch64_cpu_data[i].part_no))
{
- if (n_cores == 2)
- goto not_found;
+ if (n_cores == 2)
+ goto not_found;
- cores[n_cores++] = cpu_data[i].part_no;
- core_idx = i;
- arch_id = cpu_data[i].arch;
- break;
+ cores[n_cores++] = aarch64_cpu_data[i].part_no;
+ core_idx = i;
+ arch_id = aarch64_cpu_data[i].arch;
+ break;
}
- continue;
- }
+ continue;
+ }
if (!tune && !processed_exts && strstr (buf, "Features") != NULL)
- {
- for (i = 0; i < num_exts; i++)
- {
- bool enabled = true;
- char *p = NULL;
- char *feat_string = concat (ext_to_feat_string[i].feat_string, NULL);
-
- p = strtok (feat_string, " ");
-
- while (p != NULL)
- {
- if (strstr (buf, p) == NULL)
- {
- enabled = false;
- break;
- }
- p = strtok (NULL, " ");
- }
- ext_string = concat (ext_string, "+", enabled ? "" : "no",
- ext_to_feat_string[i].ext, NULL);
- }
- processed_exts = true;
- }
+ {
+ for (i = 0; i < num_exts; i++)
+ {
+ char *p = NULL;
+ char *feat_string
+ = concat (aarch64_extensions[i].feat_string, NULL);
+ bool enabled = true;
+
+ /* This may be a multi-token feature string. We need
+ to match all parts, which could be in any order.
+ If this isn't a multi-token feature string, strtok is
+ just going to return a pointer to feat_string. */
+ p = strtok (feat_string, " ");
+ while (p != NULL)
+ {
+ if (strstr (buf, p) == NULL)
+ {
+ /* Failed to match this token. Turn off the
+ features we'd otherwise enable. */
+ enabled = false;
+ break;
+ }
+ p = strtok (NULL, " ");
+ }
+
+ if (enabled)
+ extension_flags |= aarch64_extensions[i].flag;
+ else
+ extension_flags &= ~(aarch64_extensions[i].flag);
+ }
+
+ processed_exts = true;
+ }
}
fclose (f);
@@ -251,44 +273,56 @@ host_detect_local_cpu (int argc, const char **argv)
if (arch)
{
- const char* arch_name = get_arch_name_from_id (arch_id);
+ struct aarch64_arch_driver_info* arch_info = get_arch_from_id (arch_id);
/* We got some arch indentifier that's not in aarch64-arches.def? */
- if (!arch_name)
- goto not_found;
+ if (!arch_info)
+ goto not_found;
- res = concat ("-march=", arch_name, NULL);
+ res = concat ("-march=", arch_info->name, NULL);
+ default_flags = arch_info->flags;
}
/* We have big.LITTLE. */
else if (n_cores == 2)
{
- for (i = 0; cpu_data[i].name != NULL; i++)
- {
- if (strchr (cpu_data[i].part_no, '.') != NULL
- && strncmp (cpu_data[i].implementer_id, imps[0], strlen (imps[0]) - 1) == 0
- && valid_bL_string_p (cores, cpu_data[i].part_no))
- {
- res = concat ("-m", cpu ? "cpu" : "tune", "=", cpu_data[i].name, NULL);
- break;
- }
- }
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ {
+ if (strchr (aarch64_cpu_data[i].part_no, '.') != NULL
+ && strncmp (aarch64_cpu_data[i].implementer_id,
+ imps[0],
+ strlen (imps[0]) - 1) == 0
+ && valid_bL_string_p (cores, aarch64_cpu_data[i].part_no))
+ {
+ res = concat ("-m",
+ cpu ? "cpu" : "tune", "=",
+ aarch64_cpu_data[i].name,
+ NULL);
+ default_flags = aarch64_cpu_data[i].flags;
+ break;
+ }
+ }
if (!res)
- goto not_found;
+ goto not_found;
}
/* The simple, non-big.LITTLE case. */
else
{
- if (strncmp (cpu_data[core_idx].implementer_id, imps[0],
- strlen (imps[0]) - 1) != 0)
- goto not_found;
+ if (strncmp (aarch64_cpu_data[core_idx].implementer_id, imps[0],
+ strlen (imps[0]) - 1) != 0)
+ goto not_found;
res = concat ("-m", cpu ? "cpu" : "tune", "=",
- cpu_data[core_idx].name, NULL);
+ aarch64_cpu_data[core_idx].name, NULL);
+ default_flags = aarch64_cpu_data[core_idx].flags;
}
if (tune)
return res;
+ ext_string
+ = aarch64_get_extension_string_for_isa_flags (extension_flags,
+ default_flags).c_str ();
+
res = concat (res, ext_string, NULL);
return res;
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 5cf1efca8dd..b2d46f10646 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1597,6 +1597,9 @@ ARM target prefers @code{LDRD} and @code{STRD} instructions over
@subsubsection AArch64-specific attributes
@table @code
+@item aarch64_asm_<ext>_ok
+AArch64 assembler supports the architecture extension @code{ext} via the
+@code{.arch_extension} pseudo-op.
@item aarch64_tiny
AArch64 target which generates instruction sequences for tiny memory model.
@item aarch64_small
diff --git a/gcc/testsuite/gcc.target/aarch64/assembler_arch_1.c b/gcc/testsuite/gcc.target/aarch64/assembler_arch_1.c
new file mode 100644
index 00000000000..5deea5cf0ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/assembler_arch_1.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target aarch64_asm_lse_ok } */
+/* { dg-options "-march=armv8-a" } */
+
+/* Make sure that the function header in assembly doesn't override
+ user asm arch_extension directives. */
+
+__asm__ (".arch_extension lse");
+
+void
+foo (int i, int *v)
+{
+ register int w0 asm ("w0") = i;
+ register int *x1 asm ("x1") = v;
+
+ asm volatile (
+ "\tstset %w[i], %[v]\n"
+ : [i] "+r" (w0), [v] "+Q" (v)
+ : "r" (x1)
+ : "x30");
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c b/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c
index 8eb50aafa2b..49b74d9e265 100644
--- a/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c
@@ -6,4 +6,4 @@ test (void)
return 1;
}
-/* { dg-final { scan-assembler "\.arch.*fp.*simd" } } */
+/* { dg-final { scan-assembler-times "\\.arch armv8-a\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_1.c b/gcc/testsuite/gcc.target/aarch64/target_attr_1.c
index 852ce1e9f06..0527d0c3d61 100644
--- a/gcc/testsuite/gcc.target/aarch64/target_attr_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/target_attr_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mcpu=thunderx -save-temps" } */
+/* { dg-options "-O2 -mcpu=thunderx -dA" } */
/* Test that cpu attribute overrides the command-line -mcpu. */
diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
index 02091c6c542..2d8c7b955ce 100644
--- a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
+++ b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
@@ -10,6 +10,4 @@ foo (int a)
return a + 1;
}
-/* { dg-final { scan-assembler-not "\\+fp" } } */
-/* { dg-final { scan-assembler-not "\\+crypto" } } */
-/* { dg-final { scan-assembler-not "\\+simd" } } */
+/* { dg-final { scan-assembler-times "\\.arch armv8-a\\+nofp\\+nosimd\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_7.c b/gcc/testsuite/gcc.target/aarch64/target_attr_7.c
index 32a840378ab..818d327705f 100644
--- a/gcc/testsuite/gcc.target/aarch64/target_attr_7.c
+++ b/gcc/testsuite/gcc.target/aarch64/target_attr_7.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mcpu=thunderx -save-temps" } */
+/* { dg-options "-O2 -mcpu=thunderx -dA" } */
/* Make sure that #pragma overrides command line option and
target attribute overrides the pragma. */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ef6d1f0dda5..771a0d4d593 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6304,6 +6304,23 @@ proc check_effective_target_aarch64_tiny { } {
}
}
+# Create functions to check that the AArch64 assembler supports the
+# various architecture extensions via the .arch_extension pseudo-op.
+
+foreach { aarch64_ext } { "fp" "simd" "crypto" "crc" "lse"} {
+ eval [string map [list FUNC $aarch64_ext] {
+ proc check_effective_target_aarch64_asm_FUNC_ok { } {
+ if { [istarget aarch64*-*-*] } {
+ return [check_no_compiler_messages aarch64_FUNC_assembler object {
+ __asm__ (".arch_extension FUNC");
+ } "-march=armv8-a+FUNC"]
+ } else {
+ return 0
+ }
+ }
+ }]
+}
+
proc check_effective_target_aarch64_small { } {
if { [istarget aarch64*-*-*] } {
return [check_no_compiler_messages aarch64_small object {