2013-10-27  Tobias Burnus  <burnus@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.
	* gcc.dg/gomp/openmp-simd-1.c: New.

diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4b4eb4c..c19c8c6 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -8812,7 +8812,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/tree.c b/gcc/tree.c
index 0a42109..e7d197a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4701,7 +4701,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)
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 4f79934..f3dd348 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -517,6 +521,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/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/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/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 1656000..a6a24b8 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 9ccae3b..4d97e93 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11584,6 +11584,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);
@@ -11598,6 +11600,8 @@ c_parser_omp_for (location_t loc, c_parser *parser,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    return NULL_TREE;
 
   clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
   if (cclauses)
@@ -11793,6 +11797,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
@@ -11807,6 +11813,8 @@ 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  */
+    return NULL_TREE;
   else if (c_parser_next_token_is (parser, CPP_NAME))
     {
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
@@ -12037,6 +12045,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);
@@ -12054,6 +12070,8 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    return NULL_TREE;
 
   clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
   if (cclauses)
@@ -12102,6 +12120,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);
@@ -12115,6 +12135,8 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
 	  return add_stmt (ret);
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    return NULL_TREE;
 
   clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
   if (cclauses)
@@ -12226,24 +12248,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);
@@ -12259,6 +12273,19 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
 	  add_stmt (stmt);
 	  return true;
 	}
+      else if (!flag_openmp)  /* flag_openmp_simd  */
+	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);
@@ -12880,6 +12907,8 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
 	  c_parser_omp_declare_simd (parser, context);
 	  return;
 	}
+      if (!flag_openmp)  /* flag_openmp_simd  */
+	return;
       if (strcmp (p, "reduction") == 0)
 	{
 	  c_parser_consume_token (parser);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8deffc3..d5df07f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29077,6 +29077,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,
@@ -29094,6 +29097,8 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    return NULL_TREE;
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
 				       cclauses == NULL);
@@ -29277,6 +29282,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);
@@ -29292,6 +29299,8 @@ 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  */
+    return NULL_TREE;
   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -29520,6 +29529,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)
@@ -29541,6 +29559,8 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
 	  return ret;
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    return NULL_TREE;
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
 				       cclauses == NULL);
@@ -29596,6 +29616,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,
@@ -29612,6 +29635,8 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
 	  return add_stmt (ret);
 	}
     }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    return NULL_TREE;
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
 				       cclauses == NULL);
@@ -29721,18 +29746,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 "
@@ -29741,6 +29755,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,
@@ -29756,6 +29773,19 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
 	  add_stmt (stmt);
 	  return true;
 	}
+      else if (!flag_openmp)  /* flag_openmp_simd  */
+        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);
@@ -30347,6 +30377,8 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
 				      context);
 	  return;
 	}
+      if (!flag_openmp)  /* flag_openmp_simd  */
+	return;
       cp_ensure_no_omp_declare_simd (parser);
       if (strcmp (p, "reduction") == 0)
 	{
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ab25922..0f213ec 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}
@@ -1826,7 +1826,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/testsuite/g++.dg/gomp/openmp-simd-1.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C
new file mode 100644
index 0000000..8f8f140
--- /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 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-1.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c
new file mode 100644
index 0000000..8f8f140
--- /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 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" } } */
