@@ -818,7 +818,7 @@ const struct attribute_spec c_common_attribute_table[] =
handle_omp_declare_simd_attribute, false },
{ "cilk simd function", 0, -1, true, false, false,
handle_omp_declare_simd_attribute, false },
- { "simd", 0, 0, true, false, false,
+ { "simd", 0, 1, true, false, false,
handle_simd_attribute, false },
{ "omp declare target", 0, 0, true, false, false,
handle_omp_declare_target_attribute, false },
@@ -9032,7 +9032,7 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
/* Handle a "simd" attribute. */
static tree
-handle_simd_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+handle_simd_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
{
@@ -9045,9 +9045,41 @@ handle_simd_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
*no_add_attrs = true;
}
else
- DECL_ATTRIBUTES (*node)
- = tree_cons (get_identifier ("omp declare simd"),
- NULL_TREE, DECL_ATTRIBUTES (*node));
+ {
+ tree t = get_identifier ("omp declare simd");
+ tree attr = NULL_TREE;
+ if (args)
+ {
+ tree id = TREE_VALUE (args);
+
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("attribute %qE argument not a string", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (strcmp (TREE_STRING_POINTER (id), "notinbranch") == 0)
+ attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+ OMP_CLAUSE_NOTINBRANCH);
+ else
+ if (strcmp (TREE_STRING_POINTER (id), "inbranch") == 0)
+ attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+ OMP_CLAUSE_INBRANCH);
+ else
+ {
+ error ("only %<inbranch%> and %<notinbranch%> flags are "
+ "allowed for %<__simd__%> attribute");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ DECL_ATTRIBUTES (*node) = tree_cons (t,
+ build_tree_list (NULL_TREE,
+ attr),
+ DECL_ATTRIBUTES (*node));
+ }
}
else
{
@@ -3144,6 +3144,7 @@ At the function call it will create resolver @code{ifunc}, that will
dynamically call a clone suitable for current architecture.
@item simd
+@itemx simd("@var{mask}")
@cindex @code{simd} function attribute.
This attribute enables creation of one or more function versions that
can process multiple arguments using SIMD instructions from a
@@ -3158,6 +3159,9 @@ attribute on the same function.
If the attribute is specified and @code{#pragma omp declare simd}
present on a declaration and @code{-fopenmp} or @code{-fopenmp-simd}
switch is specified, then the attribute is ignored.
+The optional argument @var{mask} may have "notinbranch" or "inbranch"
+value and instructs the compiler to generate non-masked or masked
+clones correspondingly. By default, all clones are generated.
@item target (@var{options})
@cindex @code{target} function attribute
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+__attribute__((__simd__("notinbranch")))
+int simd_attr (void)
+{
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "simd_attr\[ \\t\]simdclone|vector" "optimized" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN4_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGVbM4_simd_attr:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGVcM4_simd_attr:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGVdM8_simd_attr:" { target { i?86-*-* x86_64-*-* } } } } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+__attribute__((simd("inbranch")))
+int simd_attr2 (void)
+{
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "simd_attr2\[ \\t\]simdclone|vector" "optimized" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGVbN4_simd_attr2:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGVcN4_simd_attr2:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGVdN8_simd_attr2:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbM4_simd_attr2:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4_simd_attr2:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM8_simd_attr2:" 1 { target { i?86-*-* x86_64-*-* } } } } */
new file mode 100644
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+__attribute__((__simd__("bug")))
+int simd_attr (void) { return 0; } /* { dg-error "only 'inbranch' and 'notinbranch'" } */
+
+__attribute__((__simd__("notinbranch", "inbranch")))
+int simd_attr2 (void) { return 0; } /* { dg-error "wrong number of arguments specified" } */