Am 31.10.2013 17:40, schrieb Jakub Jelinek:
On Sun, Oct 27, 2013 at 10:45:57PM +0100, Tobias Burnus wrote:
The code is written such that when "-fopenmp" is used,
-f(no-)openmp-simd has no effect. The following "simd" pragmas are
listed in OpenMP 4.0 - and will all get translated into "#pragma omp
simd", only, with -fopenmp-simd: [...]
I think we should also parse
#pragma omp declare reduction
Done.

Also, it would be nice if the testcases for this option included also
some clauses (both valid clauses for the simd itself and clauses valid
for the other combined constructs together with simd that they are parsed
but then thrown away).

Admittedly, my example is not that extended, but I added one. See new test cases.

Bootstrapped on x86-64-gnu-linux and regtested.
OK?

Tobias
2013-11-04  Tobias Burnus  <bur...@net-b.de>

gcc/
	* doc/invoke.texi (-fopenmp-simd): Document new option.
	* gimplify.c (gimplify_body): Accept -fopenmp-simd.
	* omp-low.c (execute_expand_omp, execute_lower_omp): Ditto.
	* tree.c (attribute_value_equal): Ditto.

gcc/fortran/
	* lang.opt (fopenmp-simd): New option.
	* gfortran.h (gfc_option_t): Add gfc_flag_openmp_simd.
	* options.c (gfc_handle_option): Handle it.

gcc/c-family/
	* c.opt (fopenmp-simd): New option.
	* c-pragma.c (omp_pragmas): Move pragmas which can contain simd to ...
	(omp_pragmas): ... this new struct.
	(c_pp_lookup_pragma): Also walk omp_pragmas.
	(init_pragma): Init pragmas for -fopenmp-simd.

gcc/c
	* c-parser.c (c_parser_omp_for, c_parser_omp_parallel,
	c_parser_omp_distribute, c_parser_omp_teams,
	c_parser_omp_target, c_parser_omp_declare): Handle
	-fopenmp-simd.

gcc/cp
	* parser.c (cp_parser_omp_for, cp_parser_omp_parallel,
	cp_parser_omp_distribute, cp_parser_omp_teams, cp_parser_omp_target,
	cp_parser_omp_declare): Handle
	-fopenmp-simd.

gcc/testsuite/
	* g++.dg/gomp/openmp-simd-1.C: New.
	* g++.dg/gomp/openmp-simd-2.C: New.
	* gcc.dg/gomp/openmp-simd-1.c: New.
	* gcc.dg/gomp/openmp-simd-2.c: New.

diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 3ce77a2..c75b087 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1170,31 +1170,35 @@ static const struct omp_pragma_def omp_pragmas[] = {
   { "cancel", PRAGMA_OMP_CANCEL },
   { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
   { "critical", PRAGMA_OMP_CRITICAL },
-  { "declare", PRAGMA_OMP_DECLARE_REDUCTION },
-  { "distribute", PRAGMA_OMP_DISTRIBUTE },
   { "end", PRAGMA_OMP_END_DECLARE_TARGET },
   { "flush", PRAGMA_OMP_FLUSH },
-  { "for", PRAGMA_OMP_FOR },
   { "master", PRAGMA_OMP_MASTER },
   { "ordered", PRAGMA_OMP_ORDERED },
-  { "parallel", PRAGMA_OMP_PARALLEL },
   { "section", PRAGMA_OMP_SECTION },
   { "sections", PRAGMA_OMP_SECTIONS },
-  { "simd", PRAGMA_OMP_SIMD },
   { "single", PRAGMA_OMP_SINGLE },
-  { "target", PRAGMA_OMP_TARGET },
-  { "task", PRAGMA_OMP_TASK },
   { "taskgroup", PRAGMA_OMP_TASKGROUP },
   { "taskwait", PRAGMA_OMP_TASKWAIT },
   { "taskyield", PRAGMA_OMP_TASKYIELD },
-  { "teams", PRAGMA_OMP_TEAMS },
   { "threadprivate", PRAGMA_OMP_THREADPRIVATE }
 };
+static const struct omp_pragma_def omp_pragmas_simd[] = {
+  { "declare", PRAGMA_OMP_DECLARE_REDUCTION },
+  { "distribute", PRAGMA_OMP_DISTRIBUTE },
+  { "for", PRAGMA_OMP_FOR },
+  { "parallel", PRAGMA_OMP_PARALLEL },
+  { "simd", PRAGMA_OMP_SIMD },
+  { "target", PRAGMA_OMP_TARGET },
+  { "task", PRAGMA_OMP_TASK },
+  { "teams", PRAGMA_OMP_TEAMS },
+};
 
 void
 c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
 {
   const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
+  const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd)
+				 / sizeof (*omp_pragmas);
   int i;
 
   for (i = 0; i < n_omp_pragmas; ++i)
@@ -1205,6 +1209,14 @@ c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
 	return;
       }
 
+  for (i = 0; i < n_omp_pragmas_simd; ++i)
+    if (omp_pragmas_simd[i].id == id)
+      {
+	*space = "omp";
+	*name = omp_pragmas_simd[i].name;
+	return;
+      }
+
   if (id >= PRAGMA_FIRST_EXTERNAL
       && (id < PRAGMA_FIRST_EXTERNAL + registered_pp_pragmas.length ()))
     {
@@ -1357,6 +1369,16 @@ init_pragma (void)
 	cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
 				      omp_pragmas[i].id, true, true);
     }
+  if (flag_openmp || flag_openmp_simd)
+    {
+      const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd)
+				     / sizeof (*omp_pragmas);
+      int i;
+
+      for (i = 0; i < n_omp_pragmas_simd; ++i)
+	cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas_simd[i].name,
+				      omp_pragmas_simd[i].id, true, true);
+    }
 
   if (!flag_preprocess_only)
     cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index b862eb9..22f8939 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1069,6 +1069,10 @@ fopenmp
 C ObjC C++ ObjC++ Var(flag_openmp)
 Enable OpenMP (implies -frecursive in Fortran)
 
+fopenmp-simd
+C ObjC C++ ObjC++ Var(flag_openmp_simd)
+Enable OpenMP's SIMD directives
+
 foperator-names
 C++ ObjC++
 Recognize C++ keywords like \"compl\" and \"xor\"
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index a8f4774..4ae30c3 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11616,6 +11616,8 @@ c_parser_omp_for (location_t loc, c_parser *parser,
 	    cclauses = cclauses_buf;
 
 	  c_parser_consume_token (parser);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
 	  block = c_begin_compound_stmt (true);
 	  ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
 	  block = c_end_compound_stmt (loc, block, true);
@@ -11630,6 +11632,11 @@ c_parser_omp_for (location_t loc, c_parser *parser,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
 
   clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
   if (cclauses)
@@ -11825,6 +11832,8 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
 	cclauses = cclauses_buf;
 
       c_parser_consume_token (parser);
+      if (!flag_openmp)  /* flag_openmp_simd  */
+	return c_parser_omp_for (loc, parser, p_name, mask, cclauses);
       block = c_begin_omp_parallel ();
       c_parser_omp_for (loc, parser, p_name, mask, cclauses);
       stmt
@@ -11839,6 +11848,11 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
       c_parser_skip_to_pragma_eol (parser);
       return NULL_TREE;
     }
+  else if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
   else if (c_parser_next_token_is (parser, CPP_NAME))
     {
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
@@ -12069,6 +12083,14 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
 	  if (cclauses == NULL)
 	    cclauses = cclauses_buf;
 	  c_parser_consume_token (parser);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    {
+	      if (simd)
+		return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+	      else
+		return c_parser_omp_parallel (loc, parser, p_name, mask,
+					      cclauses);
+	    }
 	  block = c_begin_compound_stmt (true);
 	  if (simd)
 	    ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
@@ -12086,6 +12108,11 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
 
   clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
   if (cclauses)
@@ -12134,6 +12161,8 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
 	    cclauses = cclauses_buf;
 
 	  c_parser_consume_token (parser);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    return c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
 	  block = c_begin_compound_stmt (true);
 	  ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
 	  block = c_end_compound_stmt (loc, block, true);
@@ -12147,6 +12176,11 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
 	  return add_stmt (ret);
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
 
   clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
   if (cclauses)
@@ -12258,24 +12292,16 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
     {
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
 
-      if (strcmp (p, "data") == 0)
-	{
-	  c_parser_consume_token (parser);
-	  c_parser_omp_target_data (loc, parser);
-	  return true;
-	}
-      else if (strcmp (p, "update") == 0)
-	{
-	  c_parser_consume_token (parser);
-	  return c_parser_omp_target_update (loc, parser, context);
-	}
-      else if (strcmp (p, "teams") == 0)
+      if (strcmp (p, "teams") == 0)
 	{
 	  tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
 	  char p_name[sizeof ("#pragma omp target teams distribute "
 			      "parallel for simd")];
 
 	  c_parser_consume_token (parser);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    return c_parser_omp_teams (loc, parser, p_name,
+				       OMP_TARGET_CLAUSE_MASK, cclauses);
 	  strcpy (p_name, "#pragma omp target");
 	  keep_next_level ();
 	  tree block = c_begin_compound_stmt (true);
@@ -12291,6 +12317,22 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
 	  add_stmt (stmt);
 	  return true;
 	}
+      else if (!flag_openmp)  /* flag_openmp_simd  */
+	{
+	  c_parser_skip_to_pragma_eol (parser);
+	  return NULL_TREE;
+	}
+      else if (strcmp (p, "data") == 0)
+	{
+	  c_parser_consume_token (parser);
+	  c_parser_omp_target_data (loc, parser);
+	  return true;
+	}
+      else if (strcmp (p, "update") == 0)
+	{
+	  c_parser_consume_token (parser);
+	  return c_parser_omp_target_update (loc, parser, context);
+	}
     }
 
   tree stmt = make_node (OMP_TARGET);
@@ -12918,6 +12960,11 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
 	  c_parser_omp_declare_reduction (parser, context);
 	  return;
 	}
+      if (!flag_openmp)  /* flag_openmp_simd  */
+	{
+	  c_parser_skip_to_pragma_eol (parser);
+	  return;
+	}
       if (strcmp (p, "target") == 0)
 	{
 	  c_parser_consume_token (parser);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3df746a..1ff56fe 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29133,6 +29133,9 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
 	    cclauses = cclauses_buf;
 
 	  cp_lexer_consume_token (parser->lexer);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+				       cclauses);
 	  sb = begin_omp_structured_block ();
 	  save = cp_parser_begin_omp_structured_block (parser);
 	  ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
@@ -29150,6 +29153,11 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      cp_parser_require_pragma_eol (parser, pragma_tok);
+      return NULL_TREE;
+    }
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
 				       cclauses == NULL);
@@ -29333,6 +29341,8 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
 	cclauses = cclauses_buf;
 
       cp_lexer_consume_token (parser->lexer);
+      if (!flag_openmp)  /* flag_openmp_simd  */
+	return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
       block = begin_omp_parallel ();
       save = cp_parser_begin_omp_structured_block (parser);
       cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
@@ -29348,6 +29358,11 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
       cp_parser_skip_to_pragma_eol (parser, pragma_tok);
       return NULL_TREE;
     }
+  else if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      cp_parser_require_pragma_eol (parser, pragma_tok);
+      return NULL_TREE;
+    }
   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -29576,6 +29591,15 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
 	  if (cclauses == NULL)
 	    cclauses = cclauses_buf;
 	  cp_lexer_consume_token (parser->lexer);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    {
+	      if (simd)
+		return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+					   cclauses);
+	      else
+		return cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
+					       cclauses);
+	    }
 	  sb = begin_omp_structured_block ();
 	  save = cp_parser_begin_omp_structured_block (parser);
 	  if (simd)
@@ -29597,6 +29621,11 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      cp_parser_require_pragma_eol (parser, pragma_tok);
+      return NULL_TREE;
+    }
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
 				       cclauses == NULL);
@@ -29652,6 +29681,9 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
 	    cclauses = cclauses_buf;
 
 	  cp_lexer_consume_token (parser->lexer);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
+					     cclauses);
 	  sb = begin_omp_structured_block ();
 	  save = cp_parser_begin_omp_structured_block (parser);
 	  ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
@@ -29668,6 +29700,11 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
 	  return add_stmt (ret);
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      cp_parser_require_pragma_eol (parser, pragma_tok);
+      return NULL_TREE;
+    }
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
 				       cclauses == NULL);
@@ -29777,18 +29814,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
-      if (strcmp (p, "data") == 0)
-	{
-	  cp_lexer_consume_token (parser->lexer);
-	  cp_parser_omp_target_data (parser, pragma_tok);
-	  return true;
-	}
-      else if (strcmp (p, "update") == 0)
-	{
-	  cp_lexer_consume_token (parser->lexer);
-	  return cp_parser_omp_target_update (parser, pragma_tok, context);
-	}
-      else if (strcmp (p, "teams") == 0)
+      if (strcmp (p, "teams") == 0)
 	{
 	  tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
 	  char p_name[sizeof ("#pragma omp target teams distribute "
@@ -29797,6 +29823,9 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
 	  cp_lexer_consume_token (parser->lexer);
 	  strcpy (p_name, "#pragma omp target");
 	  keep_next_level (true);
+	  if (!flag_openmp)  /* flag_openmp_simd  */
+	    return cp_parser_omp_teams (parser, pragma_tok, p_name,
+					OMP_TARGET_CLAUSE_MASK, cclauses);
 	  tree sb = begin_omp_structured_block ();
 	  unsigned save = cp_parser_begin_omp_structured_block (parser);
 	  tree ret = cp_parser_omp_teams (parser, pragma_tok, p_name,
@@ -29812,6 +29841,22 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
 	  add_stmt (stmt);
 	  return true;
 	}
+      else if (!flag_openmp)  /* flag_openmp_simd  */
+	{
+	  cp_parser_require_pragma_eol (parser, pragma_tok);
+	  return NULL_TREE;
+	}
+      else if (strcmp (p, "data") == 0)
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  cp_parser_omp_target_data (parser, pragma_tok);
+	  return true;
+	}
+      else if (strcmp (p, "update") == 0)
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  return cp_parser_omp_target_update (parser, pragma_tok, context);
+	}
     }
 
   tree stmt = make_node (OMP_TARGET);
@@ -30411,6 +30456,11 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
 					   context);
 	  return;
 	}
+      if (!flag_openmp)  /* flag_openmp_simd  */
+	{
+	  cp_parser_require_pragma_eol (parser, pragma_tok);
+	  return;
+	}
       if (strcmp (p, "target") == 0)
 	{
 	  cp_lexer_consume_token (parser->lexer);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e84bca3..35f41d9 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -168,8 +168,8 @@ in the following sections.
 @gccoptlist{-ansi  -std=@var{standard}  -fgnu89-inline @gol
 -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
 -fno-asm  -fno-builtin  -fno-builtin-@var{function} @gol
--fhosted  -ffreestanding -fopenmp -fms-extensions -fplan9-extensions @gol
--trigraphs  -traditional  -traditional-cpp @gol
+-fhosted  -ffreestanding -fopenmp -fopenmp-simd -fms-extensions @gol
+-fplan9-extensions -trigraphs  -traditional  -traditional-cpp @gol
 -fallow-single-precision  -fcond-mismatch -flax-vector-conversions @gol
 -fsigned-bitfields  -fsigned-char @gol
 -funsigned-bitfields  -funsigned-char}
@@ -1839,7 +1839,16 @@ Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and
 compiler generates parallel code according to the OpenMP Application
 Program Interface v4.0 @w{@uref{http://www.openmp.org/}}.  This option
 implies @option{-pthread}, and thus is only supported on targets that
-have support for @option{-pthread}.
+have support for @option{-pthread}. @option{-fopenmp} implies
+@option{-fopenmp-simd}.
+
+@item -fopenmp-simd
+@opindex fopenmp-simd
+@cindex OpenMP SIMD
+@cindex SIMD
+Enable handling of OpenMP's SIMD directives with @code{#pragma omp}
+in C/C++ and @code{!$omp} in Fortran. Other OpenMP directives
+are ignored.
 
 @item -fcilkplus
 @opindex fcilkplus
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index b28edd8..af5e68c 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2286,6 +2286,7 @@ typedef struct
   int flag_cray_pointer;
   int flag_d_lines;
   int gfc_flag_openmp;
+  int gfc_flag_openmp_simd;
   int flag_sign_zero;
   int flag_stack_arrays;
   int flag_module_private;
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 4f79934..49d5f3a 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -517,6 +517,10 @@ fopenmp
 Fortran
 ; Documented in C
 
+fopenmp-simd
+Fortran
+; Documented in C
+
 fpack-derived
 Fortran
 Try to lay out derived types as compactly as possible
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 6e4e7c1..e05528a 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -836,6 +836,10 @@ gfc_handle_option (size_t scode, const char *arg, int value,
       gfc_option.gfc_flag_openmp = value;
       break;
 
+    case OPT_fopenmp_simd:
+      gfc_option.gfc_flag_openmp_simd = value;
+      break;
+
     case OPT_ffree_line_length_none:
       gfc_option.free_line_length = 0;
       break;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 0723027..4df9ed4 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -8871,7 +8871,7 @@ gimplify_body (tree fndecl, bool do_parms)
       nonlocal_vlas = NULL;
     }
 
-  if (flag_openmp && gimplify_omp_ctxp)
+  if ((flag_openmp || flag_openmp_simd) && gimplify_omp_ctxp)
     {
       delete_omp_context (gimplify_omp_ctxp);
       gimplify_omp_ctxp = NULL;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index a5b9210..7874ff1 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -8232,7 +8232,7 @@ execute_expand_omp (void)
 static bool
 gate_expand_omp (void)
 {
-  return (flag_openmp != 0 && !seen_error ());
+  return ((flag_openmp != 0 || flag_openmp_simd != 0) && !seen_error ());
 }
 
 namespace {
@@ -10053,7 +10053,7 @@ execute_lower_omp (void)
 
   /* This pass always runs, to provide PROP_gimple_lomp.
      But there is nothing to do unless -fopenmp is given.  */
-  if (flag_openmp == 0)
+  if (flag_openmp == 0 && flag_openmp_simd == 0)
     return 0;
 
   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C
new file mode 100644
index 0000000..fedb186
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+#pragma omp declare simd
+float bar(float b) {
+  return b*b;
+}
+
+void foo(int n, float *a, float *b)
+{
+  int i; 
+#pragma omp simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp distribute simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp distribute parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp teams distribute simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp target teams distribute simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp teams distribute parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp target teams distribute parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp simd" 9 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp distribute" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp teams" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp target" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
new file mode 100644
index 0000000..e31c1eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+  int i, u = 0;
+  struct S s, t;
+  s.s = 0; t.s = 0;
+  #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+  for (i = 0; i < 1024; i++)
+    {
+      int x = a[i];
+      s.s += x;
+      t.s += x;
+      u += x;
+    }
+  if (t.s != s.s || u != s.s)
+    abort ();
+  return s.s;
+}
+
+
+void bar(int n, float *a, float *b)
+{
+  int i; 
+#pragma omp parallel for simd num_threads(4) safelen(64)
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "Function void omp declare reduction operator\\+" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "Function void omp declare reduction foo" 2 "original" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c
new file mode 100644
index 0000000..fedb186
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+#pragma omp declare simd
+float bar(float b) {
+  return b*b;
+}
+
+void foo(int n, float *a, float *b)
+{
+  int i; 
+#pragma omp simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp distribute simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp distribute parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp teams distribute simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp target teams distribute simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp teams distribute parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+#pragma omp target teams distribute parallel for simd
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp simd" 9 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp distribute" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp teams" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp target" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c
new file mode 100644
index 0000000..e668068
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+  int i, u = 0;
+  struct S s, t;
+  s.s = 0; t.s = 0;
+  #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+  for (i = 0; i < 1024; i++)
+    {
+      int x = a[i];
+      s.s += x;
+      t.s += x;
+      u += x;
+    }
+  if (t.s != s.s || u != s.s)
+    abort ();
+  return s.s;
+}
+
+
+void bar(int n, float *a, float *b)
+{
+  int i; 
+#pragma omp parallel for simd num_threads(4) safelen(64)
+  for (i = 0; i < n ; i++)
+    a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
diff --git a/gcc/tree.c b/gcc/tree.c
index 332751a..e0e9d8d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4814,7 +4814,7 @@ attribute_value_equal (const_tree attr1, const_tree attr2)
     return (simple_cst_list_equal (TREE_VALUE (attr1),
 				   TREE_VALUE (attr2)) == 1);
 
-  if (flag_openmp
+  if ((flag_openmp || flag_openmp_simd)
       && TREE_VALUE (attr1) && TREE_VALUE (attr2)
       && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
       && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)

Reply via email to