[v2] Extend the simd function attribute

Message ID e4d46b1c-2fcc-2316-78a8-885fe10f6903@arm.com
State Superseded
Headers show
Series
  • [v2] Extend the simd function attribute
Related show

Commit Message

Szabolcs Nagy Nov. 14, 2019, 6:58 p.m.
GCC currently supports two ways to declare the availability of vector
variants of a scalar function:

  #pragma omp declare simd
  void f (void);

and

  __attribute__ ((simd))
  void f (void);

However these declare a set of symbols that are different simd variants
of f, so a library either provides definitions for all those symbols or
it cannot use these declarations. (The set of declared symbols can be
narrowed down with additional omp clauses, but not enough to allow
declaring a single symbol.)

OpenMP 5 has a declare variant feature that allows declaring more
specific simd variants, but it is complicated and still doesn't provide
a reliable mechanism (requires gcc or vendor specific extension for
unambiguous declarations). And it requires -fopenmp.

A simpler approach is to extend the gcc specific simd attribute such
that it can specify a single vector variant of simple scalar functions.
Where simple scalar functions are ones that only take and return scalar
integer or floating type values. I believe this can be achieved by

  __attribute__ ((simd (mask, simdlen, simdabi, name))))

where mask is "inbranch" or "notinbranch" like now, simdlen is an int
with the same meaning as in omp declare simd and simdabi is a string
specifying the call ABI (which the intel vector ABI calls ISA). The
name is optional and allows a library to use a different symbol name
than what the vector ABI specifies.

The simd attribute currently can be used for both declarations and
definitions, in the latter case the simd varaints of the function are
generated, which should work with the extended simd attribute too.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.


gcc/ChangeLog:

2019-11-14  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* cgraph.h (struct cgraph_simd_clone): Add simdname field.
	* doc/extend.texi: Update the simd attribute documentation.
	* tree.h (OMP_CLAUSE__SIMDABI__EXPR): Define.
	(OMP_CLAUSE__SIMDNAME__EXPR): Define.
	* tree.c (walk_tree_1): Handle new omp clauses.
	* tree-core.h (enum omp_clause_code): Likewise.
	* tree-nested.c (convert_nonlocal_omp_clauses): Likewise.
	* tree-pretty-print.c (dump_omp_clause): Likewise.
	* omp-low.c (scan_sharing_clauses): Likewise.
	* omp-simd-clone.c (simd_clone_clauses_extract): Likewise.
	(simd_clone_mangle): Handle simdname.
	* config/aarch64/aarch64.c
	(aarch64_simd_clone_compute_vecsize_and_simdlen): Warn about
	unsupported SIMD ABI.
	* config/i386/i386.c
	(ix86_simd_clone_compute_vecsize_and_simdlen): Likewise.

gcc/c-family/ChangeLog:

2019-11-14  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* c-attribs.c (handle_simd_attribute): Handle 4 arguments.

gcc/testsuite/ChangeLog:

2019-11-14  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* c-c++-common/attr-simd-5.c: Update.
	* c-c++-common/attr-simd-6.c: New test.
	* c-c++-common/attr-simd-7.c: New test.
	* c-c++-common/attr-simd-8.c: New test.

Patch

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index c62cebf7bfd..bf2301eb790 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -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,13 +3094,22 @@  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);
 
 	  if (TREE_CODE (id) != STRING_CST)
 	    {
-	      error ("attribute %qE argument not a string", name);
+	      error ("attribute %qE first argument not a string", name);
 	      *no_add_attrs = true;
 	      return NULL_TREE;
 	    }
@@ -3113,13 +3122,75 @@  handle_simd_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs
 				     OMP_CLAUSE_INBRANCH);
 	  else
 	    {
-	      error ("only %<inbranch%> and %<notinbranch%> flags are "
-		     "allowed for %<__simd__%> attribute");
+	      error ("%qE attribute first argument must be %<inbranch%> or "
+		     "%<notinbranch%>", name);
+	      *no_add_attrs = true;
+	      return NULL_TREE;
+	    }
+
+	  args = TREE_CHAIN (args);
+	}
+
+      if (args)
+	{
+	  tree arg = TREE_VALUE (args);
+
+	  arg = c_fully_fold (arg, false, NULL);
+	  if (TREE_CODE (arg) != INTEGER_CST
+	      || !INTEGRAL_TYPE_P (TREE_TYPE (arg))
+	      || tree_int_cst_sgn (arg) < 0)
+	    {
+	      error ("%qE attribute second argument must be a non-negative "
+		     "integer constant", 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 ("%qE attribute third argument not a string", name);
+	      *no_add_attrs = true;
+	      return NULL_TREE;
+	    }
+	  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 ("%qE attribute fourth argument not a string", name);
+	      *no_add_attrs = true;
+	      return NULL_TREE;
+	    }
+	  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));
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 8989f3119ac..b8cc0db5930 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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;
 
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 1dfff331a5a..acbf3509e78 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -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)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 03a7082d2fc..92c117417c6 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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.  */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 9db4f9b1d29..63ca6a7e4d3 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3572,6 +3572,9 @@  The warnings for missing or incorrect sentinels are enabled with
 
 @item simd
 @itemx simd("@var{mask}")
+@itemx simd("@var{mask}", @var{simdlen})
+@itemx simd("@var{mask}", @var{simdlen}, "@var{simdabi}")
+@itemx simd("@var{mask}", @var{simdlen}, "@var{simdabi}", "@var{name}")
 @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
@@ -3587,9 +3590,26 @@  The optional argument @var{mask} may have the value
 and instructs the compiler to generate non-masked or masked
 clones correspondingly. By default, all clones are generated.
 
-If the attribute is specified and @code{#pragma omp declare simd} is
-present on a declaration and the @option{-fopenmp} or @option{-fopenmp-simd}
-switch is specified, then the attribute is ignored.
+The optional argument @var{simdlen} is a non-negative integer
+constant specifying the number of elements processed by one call.
+By default, or when it is 0, clones are generated for the
+@var{simdlen} variants the Vector ABI specifies.
+
+The optional argument @var{simdabi} is a string specifying the
+target-dependent call ABI or SIMD ISA variant (in case there are
+multiple supported variants), the valid strings follow the rules
+of the Vector ABI document of the target. By default, all clones
+are generated.
+
+The optional argument @var{name} is a string specifying the symbol
+for the SIMD function variant, this is only valid if a single clone
+is created. By default the symbol name is determined by the name
+mangling rules of the Vector ABI document.
+
+If on a function declaration multiple simd attributes are present
+or @code{#pragma omp declare simd} directives are present and the
+@option{-fopenmp} or @option{-fopenmp-simd} switch is specified
+then the union of all function variants they describe are created.
 
 @item stack_protect
 @cindex @code{stack_protect} function attribute
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index fa76ceba33c..7b29901b9c1 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1508,6 +1508,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 ();
@@ -1688,6 +1690,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 ();
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index 76aea56bdcf..2b11f3784c5 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -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));
+	    /* Single char simdabi is the ISA of the vector ABI.  */
+	    if (simdabi[0] && simdabi[1])
+	      {
+		warning_at (OMP_CLAUSE_LOCATION (t), 0,
+			    "ignoring unsupported simd abi %qs", 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,15 @@  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);
 
+  /* Use the specified name when given instead of mangling.  */
+  str = clone_info->simdname;
+  if (str != NULL)
+    goto skip_mangle;
+
   pp_string (&pp, "_ZGV");
   pp_character (&pp, vecsize_mangle);
   pp_character (&pp, mask);
@@ -408,12 +432,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);
 
+skip_mangle:
   /* 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
diff --git a/gcc/testsuite/c-c++-common/attr-simd-5.c b/gcc/testsuite/c-c++-common/attr-simd-5.c
index 7bf3f2c0459..58f44493fb2 100644
--- a/gcc/testsuite/c-c++-common/attr-simd-5.c
+++ b/gcc/testsuite/c-c++-common/attr-simd-5.c
@@ -1,7 +1,7 @@ 
 /* { dg-do compile } */
 
 __attribute__((__simd__("bug")))
-int simd_attr (void) { return 0; } /* { dg-error "only 'inbranch' and 'notinbranch'" } */
+int simd_attr (void) { return 0; } /* { dg-error "first argument must be 'inbranch' or 'notinbranch'" } */
 
 __attribute__((__simd__("notinbranch", "inbranch")))
-int simd_attr2 (void) { return 0; } /* { dg-error "wrong number of arguments specified" } */
+int simd_attr2 (void) { return 0; } /* { dg-error "second argument must be a non-negative integer constant" } */
diff --git a/gcc/testsuite/c-c++-common/attr-simd-6.c b/gcc/testsuite/c-c++-common/attr-simd-6.c
new file mode 100644
index 00000000000..24c38fbd533
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-simd-6.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+
+__attribute__ ((simd ("inbranch", -1)))
+void f1 (void) { } /* { dg-error "second argument must be a non-negative integer constant" } */
+
+__attribute__ ((simd ("inbranch", 4, 0)))
+void f2 (void) { } /* { dg-error "third argument not a string" } */
+
+__attribute__ ((simd ("inbranch", 4, "", 0)))
+void f3 (void) { } /* { dg-error "fourth argument not a string" } */
+
+__attribute__ ((simd ("inbranch", 4, "", "foo", "bar")))
+void f4 (void) { } /* { dg-error "wrong number of arguments specified" } */
diff --git a/gcc/testsuite/c-c++-common/attr-simd-7.c b/gcc/testsuite/c-c++-common/attr-simd-7.c
new file mode 100644
index 00000000000..10ccc9d6efe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-simd-7.c
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+
+__attribute__ ((simd ("inbranch", 1)))
+void f1 (void) { } /* { dg-warning "unsupported simdlen 1" } */
+
+__attribute__ ((simd ("inbranch", 4, "foobar")))
+void f2 (void) { } /* { dg-warning "ignoring unsupported simd abi" } */
diff --git a/gcc/testsuite/c-c++-common/attr-simd-8.c b/gcc/testsuite/c-c++-common/attr-simd-8.c
new file mode 100644
index 00000000000..747860d9180
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-simd-8.c
@@ -0,0 +1,42 @@ 
+/* { dg-do compile { target aarch64*-*-* i?86-*-* x86_64-*-* } } */
+
+#if __i386__ || __x86_64__
+# define SIMDABI "b"
+#elif __aarch64__
+# define SIMDABI "n"
+#else
+# error unsupported
+#endif
+
+#ifdef __cplusplus
+# define EXTERNC extern "C"
+#else
+# define EXTERNC
+#endif
+
+EXTERNC
+__attribute__ ((simd ("notinbranch", 4)))
+float foo1 (void) { return 0; }
+
+EXTERNC
+__attribute__ ((simd ("notinbranch", 4, SIMDABI)))
+float foo2 (void) { return 0; }
+
+EXTERNC
+__attribute__ ((simd ("notinbranch", 4, SIMDABI)))
+__attribute__ ((simd ("inbranch", 4, SIMDABI)))
+float foo3 (void) { return 0; }
+
+EXTERNC
+__attribute__ ((simd ("notinbranch", 4, SIMDABI, "vec_foo4_N")))
+__attribute__ ((simd ("inbranch", 4, SIMDABI, "vec_foo4_M")))
+float foo4 (void) { return 0; }
+
+/* { dg-final { scan-assembler "_ZGV.N4_foo1:" } } */
+/* { dg-final { scan-assembler-times "_ZGV.N4_foo2:" 1 } } */
+/* { dg-final { scan-assembler-times "_ZGV.N4_foo3:" 1 } } */
+/* { dg-final { scan-assembler-times "_ZGV.M4_foo3:" 1 } } */
+/* { dg-final { scan-assembler-not "_ZGV.N4_foo4:" } } */
+/* { dg-final { scan-assembler-not "_ZGV.M4_foo4:" } } */
+/* { dg-final { scan-assembler "vec_foo4_N:" } } */
+/* { dg-final { scan-assembler "vec_foo4_M:" } } */
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 12e078882da..40f1ad6a1fe 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -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,
 
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 4df07edcf0a..7823cd6a403 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -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.  */
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 53b3f55a3e6..cd7c9603872 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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),
diff --git a/gcc/tree.c b/gcc/tree.c
index d2c9fe35995..c7cef19e8e5 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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",
@@ -12102,6 +12106,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 */
 
diff --git a/gcc/tree.h b/gcc/tree.h
index a7d39c3a74d..84b5b31b868 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1730,6 +1730,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)