@@ -448,7 +448,7 @@ const struct attribute_spec c_common_attribute_table[] =
handle_omp_declare_variant_attribute, NULL },
{ "omp declare variant variant", 0, -1, true, false, false, false,
handle_omp_declare_variant_attribute, NULL },
- { "simd", 0, 1, true, false, false, false,
+ { "simd", 0, 4, true, false, false, false,
handle_simd_attribute, NULL },
{ "omp declare target", 0, -1, true, false, false, false,
handle_omp_declare_target_attribute, NULL },
@@ -3094,6 +3094,15 @@ handle_simd_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs
{
tree t = get_identifier ("omp declare simd");
tree attr = NULL_TREE;
+
+ /* Allow
+ simd
+ simd (mask)
+ simd (mask, simdlen)
+ simd (mask, simdlen, simdabi)
+ simd (mask, simdlen, simdabi, name)
+ forms. */
+
if (args)
{
tree id = TREE_VALUE (args);
@@ -3118,8 +3127,73 @@ handle_simd_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs
*no_add_attrs = true;
return NULL_TREE;
}
+
+ args = TREE_CHAIN (args);
}
+ if (args)
+ {
+ tree arg = TREE_VALUE (args);
+
+ // TODO: simdlen == 0 means scalable ?
+ arg = c_fully_fold (arg, false, NULL);
+ if (TREE_CODE (arg) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (arg))
+ || tree_int_cst_sgn (arg) != 1)
+ {
+ error ("second argument of attribute %qE must be positive "
+ "constant integer expression", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ tree c = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+ OMP_CLAUSE_SIMDLEN);
+ OMP_CLAUSE_SIMDLEN_EXPR (c) = arg;
+ OMP_CLAUSE_CHAIN (c) = attr;
+ attr = c;
+ args = TREE_CHAIN (args);
+ }
+
+ if (args)
+ {
+ tree arg = TREE_VALUE (args);
+
+ if (TREE_CODE (arg) != STRING_CST)
+ {
+ error ("attribute %qE argument not a string", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ // TODO: verify simdabi here with target hook?
+ tree c = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+ OMP_CLAUSE__SIMDABI_);
+ OMP_CLAUSE__SIMDABI__EXPR (c) = arg;
+ OMP_CLAUSE_CHAIN (c) = attr;
+ attr = c;
+ args = TREE_CHAIN (args);
+ }
+
+ if (args)
+ {
+ tree arg = TREE_VALUE (args);
+
+ if (TREE_CODE (arg) != STRING_CST)
+ {
+ error ("attribute %qE argument not a string", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ // TODO: check identifier? check type if it's declared?
+ tree c = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+ OMP_CLAUSE__SIMDNAME_);
+ OMP_CLAUSE__SIMDNAME__EXPR (c) = arg;
+ OMP_CLAUSE_CHAIN (c) = attr;
+ attr = c;
+ args = TREE_CHAIN (args);
+ }
+
+ gcc_assert (args == NULL);
+
DECL_ATTRIBUTES (*node)
= tree_cons (t, build_tree_list (NULL_TREE, attr),
DECL_ATTRIBUTES (*node));
@@ -805,6 +805,9 @@ struct GTY(()) cgraph_simd_clone_arg {
/* Specific data for a SIMD function clone. */
struct GTY(()) cgraph_simd_clone {
+ /* Symbol associated with this clone or NULL if vector ABI name is used. */
+ const char *simdname;
+
/* Number of words in the SIMD lane associated with this clone. */
unsigned int simdlen;
@@ -21283,7 +21283,15 @@ aarch64_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
}
}
- clonei->vecsize_mangle = 'n';
+ if (clonei->vecsize_mangle == '\0')
+ clonei->vecsize_mangle = 'n';
+ else if (clonei->vecsize_mangle != 'n')
+ {
+ /* SIMD ABI is explicitly set. */
+ warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
+ "unsupported simd abi %c", clonei->vecsize_mangle);
+ return 0;
+ }
clonei->mask_mode = VOIDmode;
elt_bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type));
if (clonei->simdlen == 0)
@@ -21841,7 +21841,18 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
}
}
- if (!TREE_PUBLIC (node->decl))
+ if (clonei->vecsize_mangle != '\0')
+ {
+ /* SIMD ABI is explicitly set. */
+ if (strchr ("bcde", clonei->vecsize_mangle) == NULL)
+ {
+ warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
+ "unsupported simd abi %c", clonei->vecsize_mangle);
+ return 0;
+ }
+ ret = 1;
+ }
+ else if (!TREE_PUBLIC (node->decl))
{
/* If the function isn't exported, we can pick up just one ISA
for the clones. */
@@ -1480,6 +1480,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
install_var_local (decl, ctx);
break;
+ case OMP_CLAUSE__SIMDABI_:
+ case OMP_CLAUSE__SIMDNAME_:
case OMP_CLAUSE__CACHE_:
default:
gcc_unreachable ();
@@ -1660,6 +1662,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE__CONDTEMP_:
break;
+ case OMP_CLAUSE__SIMDABI_:
+ case OMP_CLAUSE__SIMDNAME_:
case OMP_CLAUSE__CACHE_:
default:
gcc_unreachable ();
@@ -153,6 +153,24 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
clone_info->simdlen
= TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
break;
+ case OMP_CLAUSE__SIMDABI_:
+ {
+ const char *simdabi
+ = TREE_STRING_POINTER (OMP_CLAUSE__SIMDABI__EXPR (t));
+ // TODO: only single char abi names are supported, check earlier?
+ if (!simdabi[0] || simdabi[1])
+ {
+ warning_at (OMP_CLAUSE_LOCATION (t), 0,
+ "ignoring unsupported simd abi %s", simdabi);
+ return NULL;
+ }
+ clone_info->vecsize_mangle = simdabi[0];
+ break;
+ }
+ case OMP_CLAUSE__SIMDNAME_:
+ clone_info->simdname
+ = TREE_STRING_POINTER (OMP_CLAUSE__SIMDNAME__EXPR (t));
+ break;
case OMP_CLAUSE_LINEAR:
{
tree decl = OMP_CLAUSE_DECL (t);
@@ -341,9 +359,14 @@ simd_clone_mangle (struct cgraph_node *node,
unsigned int simdlen = clone_info->simdlen;
unsigned int n;
pretty_printer pp;
+ const char *str;
gcc_assert (vecsize_mangle && simdlen);
+ str = clone_info->simdname;
+ if (str)
+ goto end;
+
pp_string (&pp, "_ZGV");
pp_character (&pp, vecsize_mangle);
pp_character (&pp, mask);
@@ -408,12 +431,13 @@ simd_clone_mangle (struct cgraph_node *node,
}
pp_underscore (&pp);
- const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
+ str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
if (*str == '*')
++str;
pp_string (&pp, str);
str = pp_formatted_text (&pp);
+end:
/* If there already is a SIMD clone with the same mangled name, don't
add another one. This can happen e.g. for
#pragma omp declare simd
@@ -415,6 +415,12 @@ enum omp_clause_code {
/* OpenMP clause: simdlen (constant-integer-expression). */
OMP_CLAUSE_SIMDLEN,
+ /* extension: SIMD call ABI. */
+ OMP_CLAUSE__SIMDABI_,
+
+ /* extension: SIMD symbol name. */
+ OMP_CLAUSE__SIMDNAME_,
+
/* OpenMP clause: device_type ({host,nohost,any}). */
OMP_CLAUSE_DEVICE_TYPE,
@@ -1372,6 +1372,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_UNIFORM:
case OMP_CLAUSE_INBRANCH:
case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE__SIMDABI_:
+ case OMP_CLAUSE__SIMDNAME_:
/* The following clauses are only allowed on OpenMP cancel and
cancellation point directives, which at this point have already
been lowered into a function call. */
@@ -984,6 +984,20 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_right_paren (pp);
break;
+ case OMP_CLAUSE__SIMDABI_:
+ pp_string (pp, "_simdabi_(");
+ dump_generic_node (pp, OMP_CLAUSE__SIMDABI__EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
+
+ case OMP_CLAUSE__SIMDNAME_:
+ pp_string (pp, "_simdname_(");
+ dump_generic_node (pp, OMP_CLAUSE__SIMDNAME__EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
+
case OMP_CLAUSE_PRIORITY:
pp_string (pp, "priority(");
dump_generic_node (pp, OMP_CLAUSE_PRIORITY_EXPR (clause),
@@ -1725,6 +1725,12 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_SIMDLEN_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SIMDLEN), 0)
+#define OMP_CLAUSE__SIMDABI__EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SIMDABI_), 0)
+
+#define OMP_CLAUSE__SIMDNAME__EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SIMDNAME_), 0)
+
#define OMP_CLAUSE__SIMDUID__DECL(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SIMDUID_), 0)
@@ -334,6 +334,8 @@ unsigned const char omp_clause_num_ops[] =
0, /* OMP_CLAUSE_PROC_BIND */
1, /* OMP_CLAUSE_SAFELEN */
1, /* OMP_CLAUSE_SIMDLEN */
+ 1, /* OMP_CLAUSE__SIMDABI_ */
+ 1, /* OMP_CLAUSE__SIMDNAME_ */
0, /* OMP_CLAUSE_DEVICE_TYPE */
0, /* OMP_CLAUSE_FOR */
0, /* OMP_CLAUSE_PARALLEL */
@@ -419,6 +421,8 @@ const char * const omp_clause_code_name[] =
"proc_bind",
"safelen",
"simdlen",
+ "_simdabi_",
+ "_simdname_",
"device_type",
"for",
"parallel",
@@ -12079,6 +12083,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
case OMP_CLAUSE__CONDTEMP_:
case OMP_CLAUSE__SCANTEMP_:
case OMP_CLAUSE__SIMDUID_:
+ case OMP_CLAUSE__SIMDABI_:
+ case OMP_CLAUSE__SIMDNAME_:
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
/* FALLTHRU */