aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-11-21 21:06:23 +0100
committerJakub Jelinek <jakub@redhat.com>2021-11-21 21:06:23 +0100
commit364539710f828851b9fac51c39033cd09aa620de (patch)
treefbfdd76f246a754c83ac16dc87fc7cca0538a7aa /gcc
parent8fef6f720a5a0a056abfa986ba870bb406ab4716 (diff)
downloadgcc-364539710f828851b9fac51c39033cd09aa620de.zip
gcc-364539710f828851b9fac51c39033cd09aa620de.tar.gz
gcc-364539710f828851b9fac51c39033cd09aa620de.tar.bz2
i386: Fix up handling of target attribute [PR101180]
As shown in the testcase below, if a function has multiple target attributes (rather than a single one with one or more arguments) or if a function gets one target attribute on one declaration and another one on another declaration, on x86 their effect is not combined into DECL_FUNCTION_SPECIFIC_TARGET, but instead only the last processed target attribute wins. aarch64 handles this right, the following patch follows what it does, i.e. only start with target_option_default_node if DECL_FUNCTION_SPECIFIC_TARGET is previously NULL (i.e. the first target attribute being processed on a function) and otherwise start from the previous DECL_FUNCTION_SPECIFIC_TARGET. 2021-11-21 Jakub Jelinek <jakub@redhat.com> PR c++/101180 * config/i386/i386-options.c (ix86_valid_target_attribute_p): If fndecl already has DECL_FUNCTION_SPECIFIC_TARGET, use that as base instead of target_option_default_node. * gcc.target/i386/pr101180.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386-options.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101180.c12
2 files changed, 16 insertions, 1 deletions
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index feff258..a4da833 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -1443,8 +1443,11 @@ ix86_valid_target_attribute_p (tree fndecl,
/* Initialize func_options to the default before its target options can
be set. */
+ tree old_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (old_target == NULL_TREE)
+ old_target = target_option_default_node;
cl_target_option_restore (&func_options, &func_options_set,
- TREE_TARGET_OPTION (target_option_default_node));
+ TREE_TARGET_OPTION (old_target));
/* FLAGS == 1 is used for target_clones attribute. */
new_target
diff --git a/gcc/testsuite/gcc.target/i386/pr101180.c b/gcc/testsuite/gcc.target/i386/pr101180.c
new file mode 100644
index 0000000..1ac4cb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101180.c
@@ -0,0 +1,12 @@
+/* PR c++/101180 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx -mno-crc32" } */
+
+#include <x86intrin.h>
+
+__attribute__((target ("avx"))) __attribute__((target ("crc32"))) void
+foo (__m256 *p, unsigned int *q)
+{
+ __m256 c = _mm256_and_ps (p[0], p[1]);
+ *q = __crc32b (*q, 0x55);
+}