+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * 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.
+
2013-11-04 Wei Mi <wmi@google.com>
* sched-rgn.c (add_branch_dependences): Keep insns in
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * 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.
+
2013-11-04 Marek Polacek <polacek@redhat.com>
PR c++/58979
{ "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)
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 ()))
{
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",
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\"
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * 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.
+
2013-11-03 Marek Polacek <polacek@redhat.com>
* c-decl.c (grokdeclarator): Add VLA instrumentation.
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);
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)
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
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);
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);
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)
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);
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)
{
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);
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);
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);
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * 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.
+
2013-11-04 Eric Botcazou <ebotcazou@adacore.com>
* decl2.c (cpp_check): Change type of first parameter and deal with
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,
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);
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);
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;
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)
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);
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,
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);
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 "
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,
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);
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);
@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}
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
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * lang.opt (fopenmp-simd): New option.
+ * gfortran.h (gfc_option_t): Add gfc_flag_openmp_simd.
+ * options.c (gfc_handle_option): Handle it.
+
2013-11-04 Ian Lance Taylor <iant@google.com>
* f95-lang.c (ATTR_LEAF_LIST): Define.
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;
Fortran
; Documented in C
+fopenmp-simd
+Fortran
+; Documented in C
+
fpack-derived
Fortran
Try to lay out derived types as compactly as possible
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;
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;
static bool
gate_expand_omp (void)
{
- return (flag_openmp != 0 && !seen_error ());
+ return ((flag_openmp != 0 || flag_openmp_simd != 0) && !seen_error ());
}
namespace {
/* 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,
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * 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.
+
2013-11-04 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* gcc.dg/superblock.c: Require scheduling support.
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
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)