@@ -1087,8 +1087,26 @@ dump_gimple_omp_for (pretty_printer *buf
if (flags & TDF_RAW)
{
- dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
- gimple_omp_body (gs));
+ const char *kind;
+ switch (gimple_omp_for_kind (gs))
+ {
+ case GF_OMP_FOR_KIND_FOR:
+ kind = "";
+ break;
+ case GF_OMP_FOR_KIND_SIMD:
+ kind = " simd";
+ break;
+ case GF_OMP_FOR_KIND_FOR_SIMD:
+ kind = " for simd";
+ break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ kind = " distribute";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ dump_gimple_fmt (buffer, spc, flags, "%G%s <%+BODY <%S>%nCLAUSES <", gs,
+ kind, gimple_omp_body (gs));
dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags);
dump_gimple_fmt (buffer, spc, flags, " >,");
for (i = 0; i < gimple_omp_for_collapse (gs); i++)
@@ -1104,7 +1122,23 @@ dump_gimple_omp_for (pretty_printer *buf
}
else
{
- pp_string (buffer, "#pragma omp for");
+ switch (gimple_omp_for_kind (gs))
+ {
+ case GF_OMP_FOR_KIND_FOR:
+ pp_string (buffer, "#pragma omp for");
+ break;
+ case GF_OMP_FOR_KIND_SIMD:
+ pp_string (buffer, "#pragma omp simd");
+ break;
+ case GF_OMP_FOR_KIND_FOR_SIMD:
+ pp_string (buffer, "#pragma omp for simd");
+ break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ pp_string (buffer, "#pragma omp distribute");
+ break;
+ default:
+ gcc_unreachable ();
+ }
dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags);
for (i = 0; i < gimple_omp_for_collapse (gs); i++)
{
@@ -1030,6 +1030,18 @@ DEFTREECODE (OMP_TASK, "omp_task", tcc_s
unspecified by the standard. */
DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
+/* OpenMP - #pragma omp simd [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
+
+/* OpenMP - #pragma omp for simd [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_FOR_SIMD, "omp_for_simd", tcc_statement, 6)
+
+/* OpenMP - #pragma omp distribute [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)
+
/* OpenMP - #pragma omp sections [clause1 ... clauseN]
Operand 0: OMP_SECTIONS_BODY: Sections body.
Operand 1: OMP_SECTIONS_CLAUSES: List of clauses. */
@@ -9350,7 +9350,7 @@ c_parser_omp_clause_untied (c_parser *pa
of clause default goes in *pdefault. */
static tree
-c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
+c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
const char *where)
{
tree clauses = NULL;
@@ -10156,7 +10156,8 @@ c_parser_omp_for_loop (location_t loc,
an error from the initialization parsing. */
if (!fail)
{
- stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
+ stmt = c_finish_omp_for (loc, OMP_FOR, declv, initv, condv,
+ incrv, body, NULL);
if (stmt)
{
if (par_clauses != NULL)
@@ -10218,15 +10219,15 @@ pop_scopes:
LOC is the location of the #pragma token.
*/
-#define OMP_FOR_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \
- | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \
- | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_FOR_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
c_parser_omp_for (location_t loc, c_parser *parser)
@@ -10367,12 +10368,12 @@ c_parser_omp_sections_scope (location_t
LOC is the location of the #pragma token.
*/
-#define OMP_SECTIONS_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SECTIONS_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
c_parser_omp_sections (location_t loc, c_parser *parser)
@@ -10400,15 +10401,15 @@ c_parser_omp_sections (location_t loc, c
LOC is the location of the #pragma token.
*/
-#define OMP_PARALLEL_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+#define OMP_PARALLEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
static tree
c_parser_omp_parallel (location_t loc, c_parser *parser)
@@ -10416,7 +10417,7 @@ c_parser_omp_parallel (location_t loc, c
enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
const char *p_name = "#pragma omp parallel";
tree stmt, clauses, par_clause, ws_clause, block;
- unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+ omp_clause_mask mask = OMP_PARALLEL_CLAUSE_MASK;
if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
@@ -10424,7 +10425,7 @@ c_parser_omp_parallel (location_t loc, c
p_kind = PRAGMA_OMP_PARALLEL_FOR;
p_name = "#pragma omp parallel for";
mask |= OMP_FOR_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
}
else if (c_parser_next_token_is (parser, CPP_NAME))
{
@@ -10435,7 +10436,7 @@ c_parser_omp_parallel (location_t loc, c
p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
p_name = "#pragma omp parallel sections";
mask |= OMP_SECTIONS_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
}
}
@@ -10481,11 +10482,11 @@ c_parser_omp_parallel (location_t loc, c
LOC is the location of the #pragma.
*/
-#define OMP_SINGLE_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SINGLE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
c_parser_omp_single (location_t loc, c_parser *parser)
@@ -10508,15 +10509,15 @@ c_parser_omp_single (location_t loc, c_p
LOC is the location of the #pragma.
*/
-#define OMP_TASK_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
- | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+#define OMP_TASK_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE))
static tree
c_parser_omp_task (location_t loc, c_parser *parser)
@@ -100,6 +100,11 @@ enum gf_mask {
GF_CALL_ALLOCA_FOR_VAR = 1 << 5,
GF_CALL_INTERNAL = 1 << 6,
GF_OMP_PARALLEL_COMBINED = 1 << 0,
+ GF_OMP_FOR_KIND_MASK = 3 << 0,
+ GF_OMP_FOR_KIND_FOR = 0 << 0,
+ GF_OMP_FOR_KIND_SIMD = 1 << 0,
+ GF_OMP_FOR_KIND_FOR_SIMD = 2 << 0,
+ GF_OMP_FOR_KIND_DISTRIBUTE = 3 << 0,
/* True on an GIMPLE_OMP_RETURN statement if the return does not require
a thread synchronization via some sort of barrier. The exact barrier
@@ -3877,6 +3882,27 @@ gimple_omp_critical_set_name (gimple gs,
}
+/* Return the kind of OMP for statemement. */
+
+static inline int
+gimple_omp_for_kind (const_gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ return (gimple_omp_subcode (g) & GF_OMP_FOR_KIND_MASK);
+}
+
+
+/* Set the OMP for kind. */
+
+static inline void
+gimple_omp_for_set_kind (gimple g, int kind)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ g->gsbase.subcode = (g->gsbase.subcode & ~GF_OMP_FOR_KIND_MASK)
+ | (kind & GF_OMP_FOR_KIND_MASK);
+}
+
+
/* Return the clauses associated with OMP_FOR GS. */
static inline tree
@@ -4742,6 +4742,9 @@ is_gimple_stmt (tree t)
case STATEMENT_LIST:
case OMP_PARALLEL:
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_FOR_SIMD:
+ case OMP_DISTRIBUTE:
case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE:
@@ -6689,6 +6692,22 @@ gimplify_omp_for (tree *expr_p, gimple_s
gfor = gimple_build_omp_for (for_body, OMP_FOR_CLAUSES (for_stmt),
TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
for_pre_body);
+ switch (TREE_CODE (for_stmt))
+ {
+ case OMP_FOR:
+ break;
+ case OMP_SIMD:
+ gimple_omp_for_set_kind (gfor, GF_OMP_FOR_KIND_SIMD);
+ break;
+ case OMP_FOR_SIMD:
+ gimple_omp_for_set_kind (gfor, GF_OMP_FOR_KIND_FOR_SIMD);
+ break;
+ case OMP_DISTRIBUTE:
+ gimple_omp_for_set_kind (gfor, GF_OMP_FOR_KIND_DISTRIBUTE);
+ break;
+ default:
+ gcc_unreachable ();
+ }
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
{
@@ -7621,6 +7640,9 @@ gimplify_expr (tree *expr_p, gimple_seq
break;
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_FOR_SIMD:
+ case OMP_DISTRIBUTE:
ret = gimplify_omp_for (expr_p, pre_p);
break;
@@ -531,7 +531,8 @@ gfc_builtin_function (tree decl)
return decl;
}
-/* So far we need just these 4 attribute types. */
+/* So far we need just these 6 attribute types. */
+#define ATTR_NULL 0
#define ATTR_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF)
#define ATTR_NOTHROW_LEAF_MALLOC_LIST (ECF_NOTHROW | ECF_LEAF | ECF_MALLOC)
#define ATTR_CONST_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF | ECF_CONST)
@@ -235,6 +235,13 @@ unsigned const char omp_clause_num_ops[]
4, /* OMP_CLAUSE_REDUCTION */
1, /* OMP_CLAUSE_COPYIN */
1, /* OMP_CLAUSE_COPYPRIVATE */
+ 2, /* OMP_CLAUSE_LINEAR */
+ 2, /* OMP_CLAUSE_ALIGNED */
+ 1, /* OMP_CLAUSE_DEPEND */
+ 1, /* OMP_CLAUSE_FROM */
+ 1, /* OMP_CLAUSE_TO */
+ 1, /* OMP_CLAUSE_UNIFORM */
+ 1, /* OMP_CLAUSE_MAP */
1, /* OMP_CLAUSE_IF */
1, /* OMP_CLAUSE_NUM_THREADS */
1, /* OMP_CLAUSE_SCHEDULE */
@@ -244,7 +251,19 @@ unsigned const char omp_clause_num_ops[]
3, /* OMP_CLAUSE_COLLAPSE */
0, /* OMP_CLAUSE_UNTIED */
1, /* OMP_CLAUSE_FINAL */
- 0 /* OMP_CLAUSE_MERGEABLE */
+ 0, /* OMP_CLAUSE_MERGEABLE */
+ 1, /* OMP_CLAUSE_DEVICE */
+ 1, /* OMP_CLAUSE_DIST_SCHEDULE */
+ 0, /* OMP_CLAUSE_INBRANCH */
+ 0, /* OMP_CLAUSE_NOTINBRANCH */
+ 1, /* OMP_CLAUSE_NUM_TEAMS */
+ 0, /* OMP_CLAUSE_PROC_BIND */
+ 1, /* OMP_CLAUSE_SAFELEN */
+ 1, /* OMP_CLAUSE_SIMDLEN */
+ 0, /* OMP_CLAUSE_FOR */
+ 0, /* OMP_CLAUSE_PARALLEL */
+ 0, /* OMP_CLAUSE_SECTIONS */
+ 0 /* OMP_CLAUSE_TASKGROUP */
};
const char * const omp_clause_code_name[] =
@@ -257,6 +276,13 @@ const char * const omp_clause_code_name[
"reduction",
"copyin",
"copyprivate",
+ "linear",
+ "aligned",
+ "depend",
+ "from",
+ "to",
+ "uniform",
+ "map",
"if",
"num_threads",
"schedule",
@@ -266,7 +292,19 @@ const char * const omp_clause_code_name[
"collapse",
"untied",
"final",
- "mergeable"
+ "mergeable",
+ "device",
+ "dist_schedule",
+ "inbranch",
+ "notinbranch",
+ "num_teams",
+ "proc_bind",
+ "safelen",
+ "simdlen",
+ "for",
+ "parallel",
+ "sections",
+ "taskgroup"
};
@@ -10761,6 +10799,16 @@ walk_tree_1 (tree *tp, walk_tree_fn func
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_UNIFORM:
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_SIMDLEN:
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
/* FALLTHRU */
@@ -10769,6 +10817,13 @@ walk_tree_1 (tree *tp, walk_tree_fn func
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PROC_BIND:
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
case OMP_CLAUSE_LASTPRIVATE:
@@ -10784,6 +10839,12 @@ walk_tree_1 (tree *tp, walk_tree_fn func
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
}
+ case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_LINEAR:
+ WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+
case OMP_CLAUSE_REDUCTION:
{
int i;
@@ -60,7 +60,8 @@ c-common.h, not after.
STMT_EXPR_NO_SCOPE (in STMT_EXPR)
BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
- OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
+ OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD, OMP_FOR_SIMD
+ and OMP_DISTRIBUTE)
BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
@@ -3976,7 +3977,7 @@ more_aggr_init_expr_args_p (const aggr_i
/* Used while gimplifying continue statements bound to OMP_FOR nodes. */
#define OMP_FOR_GIMPLIFYING_P(NODE) \
- (TREE_LANG_FLAG_0 (OMP_FOR_CHECK (NODE)))
+ (TREE_LANG_FLAG_0 (OMP_LOOP_CHECK (NODE)))
/* A language-specific token attached to the OpenMP data clauses to
hold code (or code fragments) related to ctors, dtors, and op=.
@@ -5708,17 +5709,20 @@ extern tree begin_omp_parallel (void);
extern tree finish_omp_parallel (tree, tree);
extern tree begin_omp_task (void);
extern tree finish_omp_task (tree, tree);
-extern tree finish_omp_for (location_t, tree, tree,
- tree, tree, tree, tree, tree);
+extern tree finish_omp_for (location_t, enum tree_code,
+ tree, tree, tree, tree, tree,
+ tree, tree);
extern void finish_omp_atomic (enum tree_code, enum tree_code,
tree, tree, tree, tree, tree);
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern void finish_omp_taskwait (void);
+extern void finish_omp_taskyield (void);
+extern void finish_omp_cancel (tree);
+extern void finish_omp_cancellation_point (tree);
extern tree begin_transaction_stmt (location_t, tree *, int);
extern void finish_transaction_stmt (tree, tree, int, tree);
extern tree build_transaction_expr (location_t, tree, int, tree);
-extern void finish_omp_taskyield (void);
extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool);
extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
@@ -669,6 +669,9 @@ cp_gimplify_expr (tree *expr_p, gimple_s
gcc_unreachable ();
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_FOR_SIMD:
+ case OMP_DISTRIBUTE:
ret = cp_gimplify_omp_for (expr_p, pre_p);
break;
@@ -1116,7 +1119,10 @@ cp_genericize_r (tree *stmt_p, int *walk
genericize_continue_stmt (stmt_p);
else if (TREE_CODE (stmt) == BREAK_STMT)
genericize_break_stmt (stmt_p);
- else if (TREE_CODE (stmt) == OMP_FOR)
+ else if (TREE_CODE (stmt) == OMP_FOR
+ || TREE_CODE (stmt) == OMP_SIMD
+ || TREE_CODE (stmt) == OMP_FOR_SIMD
+ || TREE_CODE (stmt) == OMP_DISTRIBUTE)
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
else if (TREE_CODE (stmt) == SIZEOF_EXPR)
{
@@ -4025,6 +4025,7 @@ tree
finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
+ bitmap_head aligned_head;
tree c, t, *pc = &clauses;
const char *name;
@@ -4032,6 +4033,7 @@ finish_omp_clauses (tree clauses)
bitmap_initialize (&generic_head, &bitmap_default_obstack);
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+ bitmap_initialize (&aligned_head, &bitmap_default_obstack);
for (pc = &clauses, c = clauses; c ; c = *pc)
{
@@ -4054,6 +4056,27 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_COPYIN:
name = "copyin";
goto check_dup_generic;
+ case OMP_CLAUSE_LINEAR:
+ name = "linear";
+ t = OMP_CLAUSE_LINEAR_STEP (c);
+ if (t == NULL_TREE)
+ t = integer_one_node;
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("linear step expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_LINEAR_STEP (c) = t;
+ }
+ goto check_dup_generic;
check_dup_generic:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
@@ -4181,12 +4204,210 @@ finish_omp_clauses (tree clauses)
}
break;
+ case OMP_CLAUSE_SIMDLEN:
+ case OMP_CLAUSE_SAFELEN:
+ t = OMP_CLAUSE_OPERAND (c, 0);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%qs length expression must be integral",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ t = maybe_constant_value (t);
+ if (!processing_template_decl)
+ {
+ if (TREE_CODE (t) != INTEGER_CST
+ || tree_int_cst_sgn (t) == -1)
+ {
+ error ("%qs length expression must be positive constant"
+ " integer expression",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ }
+ OMP_CLAUSE_OPERAND (c, 0) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_NUM_TEAMS:
+ t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<num_teams%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_DEVICE:
+ t = OMP_CLAUSE_DEVICE_ID (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<device%> id must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ t = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c);
+ if (t == NULL)
+ ;
+ else if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<dist_schedule%> chunk size expression must be "
+ "integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_ALIGNED:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not a variable in %<aligned%> clause", t);
+ else
+ error ("%qE is not a variable in %<aligned%> clause", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ error ("%qD appears more than once in %<aligned%> clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ t = OMP_CLAUSE_ALIGNED_ALIGNMENT (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<aligned%> clause alignment expression must "
+ "be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ t = maybe_constant_value (t);
+ if (!processing_template_decl)
+ {
+ if (TREE_CODE (t) != INTEGER_CST
+ || tree_int_cst_sgn (t) == -1)
+ {
+ error ("%<aligned%> clause alignment expression must be "
+ "positive constant integer expression");
+ remove = true;
+ }
+ }
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_DEPEND:
+ t = OMP_CLAUSE_DECL (c);
+ /* FIXME: depend clause argument may be also array section. */
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not a variable in %<depend%> clause", t);
+ else
+ error ("%qE is not a variable in %<depend%> clause", t);
+ remove = true;
+ }
+ break;
+
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ t = OMP_CLAUSE_DECL (c);
+ /* FIXME: map clause argument may be also array section. */
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error ("%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+ {
+ error ("%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ break;
+
+ case OMP_CLAUSE_UNIFORM:
+ if (TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not an argument in %<uniform%> clause", t);
+ else
+ error ("%qE is not an argument in %<uniform%> clause", t);
+ remove = true;
+ }
+ break;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
+ case OMP_CLAUSE_PROC_BIND:
break;
default:
@@ -4741,8 +4962,8 @@ handle_omp_for_class_iterator (int i, lo
sk_omp scope. */
tree
-finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
- tree incrv, tree body, tree pre_body, tree clauses)
+finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
+ tree condv, tree incrv, tree body, tree pre_body, tree clauses)
{
tree omp_for = NULL, orig_incr = NULL;
tree decl, init, cond, incr;
@@ -4811,7 +5032,7 @@ finish_omp_for (location_t locus, tree d
{
tree stmt;
- stmt = make_node (OMP_FOR);
+ stmt = make_node (code);
for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
{
@@ -4923,7 +5144,7 @@ finish_omp_for (location_t locus, tree d
if (IS_EMPTY_STMT (pre_body))
pre_body = NULL;
- omp_for = c_finish_omp_for (locus, declv, initv, condv, incrv,
+ omp_for = c_finish_omp_for (locus, code, declv, initv, condv, incrv,
body, pre_body);
if (omp_for == NULL)
@@ -5110,6 +5331,62 @@ finish_omp_taskyield (void)
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
finish_expr_stmt (stmt);
+}
+
+void
+finish_omp_cancel (tree clauses)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
+ int mask = 0;
+ if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ mask = 1;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ mask = 2;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ mask = 4;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ mask = 8;
+ else
+ {
+ error ("%<#pragma omp cancellation point must specify one of "
+ "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
+ return;
+ }
+ vec<tree, va_gc> *vec
+ = make_tree_vector_single (build_int_cst (integer_type_node, mask));
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
+ tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
+ if (ifc != NULL_TREE)
+ stmt = build3 (COND_EXPR, void_type_node, OMP_CLAUSE_IF_EXPR (ifc),
+ stmt, NULL_TREE);
+ finish_expr_stmt (stmt);
+}
+
+void
+finish_omp_cancellation_point (tree clauses)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
+ int mask = 0;
+ if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ mask = 1;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ mask = 2;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ mask = 4;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ mask = 8;
+ else
+ {
+ error ("%<#pragma omp cancellation point must specify one of "
+ "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
+ return;
+ }
+ vec<tree, va_gc> *vec
+ = make_tree_vector_single (build_int_cst (integer_type_node, mask));
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
+ finish_expr_stmt (stmt);
}
/* Begin a __transaction_atomic or __transaction_relaxed statement.
@@ -25709,7 +25709,7 @@ cp_parser_objc_at_dynamic_declaration (c
}
-/* OpenMP 2.5 parsing routines. */
+/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines. */
/* Returns name of the next clause.
If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
@@ -25727,6 +25727,8 @@ cp_parser_omp_clause_name (cp_parser *pa
result = PRAGMA_OMP_CLAUSE_DEFAULT;
else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_PRIVATE))
result = PRAGMA_OMP_CLAUSE_PRIVATE;
+ else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+ result = PRAGMA_OMP_CLAUSE_FOR;
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -25734,6 +25736,10 @@ cp_parser_omp_clause_name (cp_parser *pa
switch (p[0])
{
+ case 'a':
+ if (!strcmp ("aligned", p))
+ result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ break;
case 'c':
if (!strcmp ("collapse", p))
result = PRAGMA_OMP_CLAUSE_COLLAPSE;
@@ -25742,23 +25748,44 @@ cp_parser_omp_clause_name (cp_parser *pa
else if (!strcmp ("copyprivate", p))
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
break;
+ case 'd':
+ if (!strcmp ("depend", p))
+ result = PRAGMA_OMP_CLAUSE_DEPEND;
+ else if (!strcmp ("device", p))
+ result = PRAGMA_OMP_CLAUSE_DEVICE;
+ else if (!strcmp ("dist_schedule", p))
+ result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+ break;
case 'f':
if (!strcmp ("final", p))
result = PRAGMA_OMP_CLAUSE_FINAL;
else if (!strcmp ("firstprivate", p))
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
+ else if (!strcmp ("from", p))
+ result = PRAGMA_OMP_CLAUSE_FROM;
break;
+ case 'i':
+ if (!strcmp ("inbranch", p))
+ result = PRAGMA_OMP_CLAUSE_INBRANCH;
case 'l':
if (!strcmp ("lastprivate", p))
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
+ else if (!strcmp ("linear", p))
+ result = PRAGMA_OMP_CLAUSE_LINEAR;
break;
case 'm':
- if (!strcmp ("mergeable", p))
+ if (!strcmp ("map", p))
+ result = PRAGMA_OMP_CLAUSE_MAP;
+ else if (!strcmp ("mergeable", p))
result = PRAGMA_OMP_CLAUSE_MERGEABLE;
break;
case 'n':
- if (!strcmp ("nowait", p))
+ if (!strcmp ("notinbranch", p))
+ result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
+ else if (!strcmp ("nowait", p))
result = PRAGMA_OMP_CLAUSE_NOWAIT;
+ else if (!strcmp ("num_teams", p))
+ result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
else if (!strcmp ("num_threads", p))
result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
break;
@@ -25766,18 +25793,38 @@ cp_parser_omp_clause_name (cp_parser *pa
if (!strcmp ("ordered", p))
result = PRAGMA_OMP_CLAUSE_ORDERED;
break;
+ case 'p':
+ if (!strcmp ("parallel", p))
+ result = PRAGMA_OMP_CLAUSE_PARALLEL;
+ else if (!strcmp ("proc_bind", p))
+ result = PRAGMA_OMP_CLAUSE_PROC_BIND;
+ break;
case 'r':
if (!strcmp ("reduction", p))
result = PRAGMA_OMP_CLAUSE_REDUCTION;
break;
case 's':
- if (!strcmp ("schedule", p))
+ if (!strcmp ("safelen", p))
+ result = PRAGMA_OMP_CLAUSE_SAFELEN;
+ else if (!strcmp ("schedule", p))
result = PRAGMA_OMP_CLAUSE_SCHEDULE;
+ else if (!strcmp ("sections", p))
+ result = PRAGMA_OMP_CLAUSE_SECTIONS;
else if (!strcmp ("shared", p))
result = PRAGMA_OMP_CLAUSE_SHARED;
+ else if (!strcmp ("simdlen", p))
+ result = PRAGMA_OMP_CLAUSE_SIMDLEN;
+ break;
+ case 't':
+ if (!strcmp ("taskgroup", p))
+ result = PRAGMA_OMP_CLAUSE_TASKGROUP;
+ else if (!strcmp ("to", p))
+ result = PRAGMA_OMP_CLAUSE_TO;
break;
case 'u':
- if (!strcmp ("untied", p))
+ if (!strcmp ("uniform", p))
+ result = PRAGMA_OMP_CLAUSE_UNIFORM;
+ else if (!strcmp ("untied", p))
result = PRAGMA_OMP_CLAUSE_UNTIED;
break;
}
@@ -25810,20 +25857,26 @@ check_no_duplicate_clause (tree clauses,
identifier
variable-list , identifier
- In addition, we match a closing parenthesis. An opening parenthesis
- will have been consumed by the caller.
+ In addition, we match a closing parenthesis (or, if COLON is non-NULL,
+ colon). An opening parenthesis will have been consumed by the caller.
If KIND is nonzero, create the appropriate node and install the decl
in OMP_CLAUSE_DECL and add the node to the head of the list.
If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
- return the list created. */
+ return the list created.
+
+ COLON can be NULL if only closing parenthesis should end the list,
+ or pointer to bool which will receive false if the list is terminated
+ by closing parenthesis or true if the list is terminated by colon. */
static tree
cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
- tree list)
+ tree list, bool *colon)
{
cp_token *token;
+ if (colon)
+ *colon = false;
while (1)
{
tree name, decl;
@@ -25857,6 +25910,13 @@ cp_parser_omp_var_list_no_open (cp_parse
cp_lexer_consume_token (parser->lexer);
}
+ if (colon != NULL && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ *colon = true;
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ return list;
+ }
+
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
{
int ending;
@@ -25882,7 +25942,7 @@ static tree
cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
{
if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
- return cp_parser_omp_var_list_no_open (parser, kind, list);
+ return cp_parser_omp_var_list_no_open (parser, kind, list, NULL);
return list;
}
@@ -26198,7 +26258,8 @@ cp_parser_omp_clause_reduction (cp_parse
if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
goto resync_fail;
- nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list,
+ NULL);
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_REDUCTION_CODE (c) = code;
@@ -26313,12 +26374,393 @@ cp_parser_omp_clause_untied (cp_parser *
return c;
}
+/* OpenMP 4.0:
+ inbranch
+ notinbranch */
+
+static tree
+cp_parser_omp_clause_branch (cp_parser * /*parser*/, enum omp_clause_code code,
+ tree list, location_t location)
+{
+ check_no_duplicate_clause (list, code, omp_clause_code_name[code], location);
+ tree c = build_omp_clause (location, code);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ parallel
+ for
+ sections
+ taskgroup */
+
+static tree
+cp_parser_omp_clause_cancelkind (cp_parser * /*parser*/,
+ enum omp_clause_code code,
+ tree list, location_t location)
+{
+ tree c;
+
+ for (c = list; c; c = OMP_CLAUSE_CHAIN (c))
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
+ error_at (location, "only one of %<parallel%>, %<for%>, %<sections%> "
+ "and %<taskgroup%> clauses can be specified");
+ break;
+ default:
+ break;
+ }
+ c = build_omp_clause (location, code);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ num_teams ( expression ) */
+
+static tree
+cp_parser_omp_clause_num_teams (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS,
+ "num_teams", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_NUM_TEAMS);
+ OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ aligned ( variable-list )
+ aligned ( variable-list : constant-expression ) */
+
+static tree
+cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
+{
+ tree nlist, c, alignment = NULL_TREE;
+ bool colon;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALIGNED, list,
+ &colon);
+
+ if (colon)
+ {
+ alignment = cp_parser_constant_expression (parser, false, NULL);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ if (alignment == error_mark_node)
+ alignment = NULL_TREE;
+ }
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
+
+ return nlist;
+}
+
+/* OpenMP 4.0:
+ linear ( variable-list )
+ linear ( variable-list : expression ) */
+
+static tree
+cp_parser_omp_clause_linear (cp_parser *parser, tree list)
+{
+ tree nlist, c, step = integer_one_node;
+ bool colon;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LINEAR, list,
+ &colon);
+
+ if (colon)
+ {
+ step = cp_parser_expression (parser, false, NULL);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ if (step == error_mark_node)
+ return list;
+ }
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_LINEAR_STEP (c) = step;
+
+ return nlist;
+}
+
+/* OpenMP 4.0:
+ depend ( depend-kind : variable-list )
+
+ depend-kind:
+ in | out | inout */
+
+static tree
+cp_parser_omp_clause_depend (cp_parser *parser, tree list)
+{
+ tree nlist, c;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("in", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_IN;
+ else if (strcmp ("inout", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (strcmp ("out", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_OUT;
+ else
+ goto invalid_kind;
+ }
+ else
+ goto invalid_kind;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto resync_fail;
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND, list,
+ NULL);
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_DEPEND_KIND (c) = kind;
+
+ return nlist;
+
+ invalid_kind:
+ cp_parser_error (parser, "invalid depend kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+}
+
+/* OpenMP 4.0:
+ map ( map-kind : variable-list )
+ map ( variable-list)
+
+ map-kind:
+ alloc | to | from | tofrom */
+
+static tree
+cp_parser_omp_clause_map (cp_parser *parser, tree list)
+{
+ tree nlist, c;
+ enum omp_clause_map_kind kind = OMP_CLAUSE_MAP_TOFROM;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("alloc", p) == 0)
+ kind = OMP_CLAUSE_MAP_ALLOC;
+ else if (strcmp ("to", p) == 0)
+ kind = OMP_CLAUSE_MAP_TO;
+ else if (strcmp ("from", p) == 0)
+ kind = OMP_CLAUSE_MAP_FROM;
+ else if (strcmp ("tofrom", p) == 0)
+ kind = OMP_CLAUSE_MAP_TOFROM;
+ else
+ {
+ cp_parser_error (parser, "invalid map kind");
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list,
+ NULL);
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_MAP_KIND (c) = kind;
+
+ return nlist;
+}
+
+/* OpenMP 4.0:
+ device ( expression ) */
+
+static tree
+cp_parser_omp_clause_device (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE,
+ "device", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_DEVICE);
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ dist_schedule ( static )
+ dist_schedule ( static , expression ) */
+
+static tree
+cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree c, t;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE);
+
+ if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
+ goto invalid_kind;
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ t = cp_parser_assignment_expression (parser, false, NULL);
+
+ if (t == error_mark_node)
+ goto resync_fail;
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ goto resync_fail;
+ }
+ else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
+ goto resync_fail;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, "dist_schedule",
+ location);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+
+ invalid_kind:
+ cp_parser_error (parser, "invalid dist_schedule kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+}
+
+/* OpenMP 4.0:
+ proc_bind ( proc-bind-kind )
+
+ proc-bind-kind:
+ master | close | spread */
+
+static tree
+cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree c;
+ enum omp_clause_proc_bind_kind kind;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("master", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_MASTER;
+ else if (strcmp ("close", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_CLOSE;
+ else if (strcmp ("spread", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_SPREAD;
+ else
+ goto invalid_kind;
+ }
+ else
+ goto invalid_kind;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto resync_fail;
+
+ c = build_omp_clause (location, OMP_CLAUSE_PROC_BIND);
+ check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind",
+ location);
+ OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+
+ invalid_kind:
+ cp_parser_error (parser, "invalid depend kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+}
+
/* Parse all OpenMP clauses. The set clauses allowed by the directive
is a bitmask in MASK. Return the list of clauses found; the result
of clause default goes in *pdefault. */
static tree
-cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
+cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
const char *where, cp_token *pragma_tok)
{
tree clauses = NULL;
@@ -26418,7 +26860,89 @@ cp_parser_omp_all_clauses (cp_parser *pa
case PRAGMA_OMP_CLAUSE_UNTIED:
clauses = cp_parser_omp_clause_untied (parser, clauses,
token->location);
- c_name = "nowait";
+ c_name = "untied";
+ break;
+ case PRAGMA_OMP_CLAUSE_INBRANCH:
+ clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
+ clauses, token->location);
+ c_name = "inbranch";
+ break;
+ case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
+ clauses = cp_parser_omp_clause_branch (parser,
+ OMP_CLAUSE_NOTINBRANCH,
+ clauses, token->location);
+ c_name = "notinbranch";
+ break;
+ case PRAGMA_OMP_CLAUSE_PARALLEL:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
+ clauses, token->location);
+ c_name = "parallel";
+ break;
+ case PRAGMA_OMP_CLAUSE_FOR:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
+ clauses, token->location);
+ c_name = "for";
+ break;
+ case PRAGMA_OMP_CLAUSE_SECTIONS:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
+ clauses, token->location);
+ c_name = "sections";
+ break;
+ case PRAGMA_OMP_CLAUSE_TASKGROUP:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
+ clauses, token->location);
+ c_name = "taskgroup";
+ break;
+ case PRAGMA_OMP_CLAUSE_TO:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO,
+ clauses);
+ c_name = "to";
+ break;
+ case PRAGMA_OMP_CLAUSE_FROM:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM,
+ clauses);
+ c_name = "from";
+ break;
+ case PRAGMA_OMP_CLAUSE_UNIFORM:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_UNIFORM,
+ clauses);
+ c_name = "uniform";
+ break;
+ case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
+ clauses = cp_parser_omp_clause_num_teams (parser, clauses,
+ token->location);
+ c_name = "num_teams";
+ break;
+ case PRAGMA_OMP_CLAUSE_ALIGNED:
+ clauses = cp_parser_omp_clause_aligned (parser, clauses);
+ c_name = "aligned";
+ break;
+ case PRAGMA_OMP_CLAUSE_LINEAR:
+ clauses = cp_parser_omp_clause_linear (parser, clauses);
+ c_name = "linear";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEPEND:
+ clauses = cp_parser_omp_clause_depend (parser, clauses);
+ c_name = "depend";
+ break;
+ case PRAGMA_OMP_CLAUSE_MAP:
+ clauses = cp_parser_omp_clause_map (parser, clauses);
+ c_name = "map";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEVICE:
+ clauses = cp_parser_omp_clause_device (parser, clauses,
+ token->location);
+ c_name = "device";
+ break;
+ case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
+ clauses = cp_parser_omp_clause_dist_schedule (parser, clauses,
+ token->location);
+ c_name = "dist_schedule";
+ break;
+ case PRAGMA_OMP_CLAUSE_PROC_BIND:
+ clauses = cp_parser_omp_clause_proc_bind (parser, clauses,
+ token->location);
+ c_name = "proc_bind";
break;
default:
cp_parser_error (parser, "expected %<#pragma omp%> clause");
@@ -27075,7 +27599,8 @@ cp_parser_omp_for_incr (cp_parser *parse
/* Parse the restricted form of the for statement allowed by OpenMP. */
static tree
-cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
+cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
+ tree *par_clauses)
{
tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
tree real_decl, initv, condv, incrv, declv;
@@ -27434,7 +27959,7 @@ cp_parser_omp_for_loop (cp_parser *parse
if (declv == NULL_TREE)
ret = NULL_TREE;
else
- ret = finish_omp_for (loc_first, declv, initv, condv, incrv, body,
+ ret = finish_omp_for (loc_first, code, declv, initv, condv, incrv, body,
pre_body, clauses);
while (nbraces)
@@ -27467,33 +27992,86 @@ cp_parser_omp_for_loop (cp_parser *parse
return ret;
}
+/* OpenMP 4.0:
+ #pragma omp simd simd-clause[optseq] new-line
+ for-loop */
+
+#define OMP_SIMD_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree clauses, sb, ret;
+ unsigned int save;
+
+ clauses = cp_parser_omp_all_clauses (parser, OMP_SIMD_CLAUSE_MASK,
+ "#pragma omp simd", pragma_tok);
+
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+
+ ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, NULL);
+
+ cp_parser_end_omp_structured_block (parser, save);
+ add_stmt (finish_omp_structured_block (sb));
+
+ return ret;
+}
+
/* OpenMP 2.5:
#pragma omp for for-clause[optseq] new-line
+ for-loop
+
+ OpenMP 4.0:
+ #pragma omp for simd for-simd-clause[optseq] new-line
for-loop */
-#define OMP_FOR_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \
- | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT) \
- | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE))
+#define OMP_FOR_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
{
tree clauses, sb, ret;
unsigned int save;
+ enum tree_code code = OMP_FOR;
+ omp_clause_mask mask = OMP_FOR_CLAUSE_MASK;
+ const char *p_name = "#pragma omp for";
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "simd") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ code = OMP_FOR_SIMD;
+ mask |= OMP_SIMD_CLAUSE_MASK;
+ p_name = "#pragma omp for simd";
+ }
+ }
- clauses = cp_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
- "#pragma omp for", pragma_tok);
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, clauses, NULL);
+ ret = cp_parser_omp_for_loop (parser, code, clauses, NULL);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -27612,12 +28190,12 @@ cp_parser_omp_sections_scope (cp_parser
# pragma omp sections sections-clause[optseq] newline
sections-scope */
-#define OMP_SECTIONS_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SECTIONS_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok)
@@ -27637,17 +28215,21 @@ cp_parser_omp_sections (cp_parser *parse
/* OpenMP 2.5:
# pragma parallel parallel-clause new-line
# pragma parallel for parallel-for-clause new-line
- # pragma parallel sections parallel-sections-clause new-line */
+ # pragma parallel sections parallel-sections-clause new-line
+
+ OpenMP 4.0:
+ # pragma parallel for simd parallel-for-simd-clause new-line */
-#define OMP_PARALLEL_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+#define OMP_PARALLEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
@@ -27655,7 +28237,7 @@ cp_parser_omp_parallel (cp_parser *parse
enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
const char *p_name = "#pragma omp parallel";
tree stmt, clauses, par_clause, ws_clause, block;
- unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+ omp_clause_mask mask = OMP_PARALLEL_CLAUSE_MASK;
unsigned int save;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -27665,7 +28247,20 @@ cp_parser_omp_parallel (cp_parser *parse
p_kind = PRAGMA_OMP_PARALLEL_FOR;
p_name = "#pragma omp parallel for";
mask |= OMP_FOR_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "simd") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ p_kind = PRAGMA_OMP_PARALLEL_FOR_SIMD;
+ p_name = "#pragma omp parallel for simd";
+ mask |= OMP_SIMD_CLAUSE_MASK;
+ }
+ }
}
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -27677,7 +28271,7 @@ cp_parser_omp_parallel (cp_parser *parse
p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
p_name = "#pragma omp parallel sections";
mask |= OMP_SECTIONS_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
}
}
@@ -27694,7 +28288,12 @@ cp_parser_omp_parallel (cp_parser *parse
case PRAGMA_OMP_PARALLEL_FOR:
c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
+ cp_parser_omp_for_loop (parser, OMP_FOR, ws_clause, &par_clause);
+ break;
+
+ case PRAGMA_OMP_PARALLEL_FOR_SIMD:
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+ cp_parser_omp_for_loop (parser, OMP_FOR_SIMD, ws_clause, &par_clause);
break;
case PRAGMA_OMP_PARALLEL_SECTIONS:
@@ -27719,11 +28318,11 @@ cp_parser_omp_parallel (cp_parser *parse
# pragma omp single single-clause[optseq] new-line
structured-block */
-#define OMP_SINGLE_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SINGLE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
@@ -27743,15 +28342,16 @@ cp_parser_omp_single (cp_parser *parser,
# pragma omp task task-clause[optseq] new-line
structured-block */
-#define OMP_TASK_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
- | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+#define OMP_TASK_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND))
static tree
cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
@@ -27802,6 +28402,63 @@ cp_parser_omp_threadprivate (cp_parser *
finish_omp_threadprivate (vars);
}
+/* OpenMP 4.0:
+ # pragma omp cancel cancel-clause[optseq] new-line */
+
+#define OMP_CANCEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static void
+cp_parser_omp_cancel (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree clauses = cp_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
+ "#pragma omp cancel", pragma_tok);
+ finish_omp_cancel (clauses);
+}
+
+/* OpenMP 4.0:
+ # pragma omp cancellation point cancelpt-clause[optseq] new-line */
+
+#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
+
+static void
+cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree clauses;
+ bool point_seen = false;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "point") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ point_seen = true;
+ }
+ }
+ if (!point_seen)
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return;
+ }
+
+ clauses = cp_parser_omp_all_clauses (parser,
+ OMP_CANCELLATION_POINT_CLAUSE_MASK,
+ "#pragma omp cancellation point",
+ pragma_tok);
+ finish_omp_cancellation_point (clauses);
+}
+
/* Main entry point to OpenMP statement pragmas. */
static void
@@ -27832,6 +28489,9 @@ cp_parser_omp_construct (cp_parser *pars
case PRAGMA_OMP_SECTIONS:
stmt = cp_parser_omp_sections (parser, pragma_tok);
break;
+ case PRAGMA_OMP_SIMD:
+ stmt = cp_parser_omp_simd (parser, pragma_tok);
+ break;
case PRAGMA_OMP_SINGLE:
stmt = cp_parser_omp_single (parser, pragma_tok);
break;
@@ -28264,6 +28924,38 @@ cp_parser_pragma (cp_parser *parser, enu
}
break;
+ case PRAGMA_OMP_CANCEL:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_cancel (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location,
+ "%<#pragma omp cancel%> may only be "
+ "used in compound statements");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
+ case PRAGMA_OMP_CANCELLATION_POINT:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_cancellation_point (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location,
+ "%<#pragma omp cancellation point%> may only be "
+ "used in compound statements");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
case PRAGMA_OMP_THREADPRIVATE:
cp_parser_omp_threadprivate (parser, pragma_tok);
return false;
@@ -28275,6 +28967,7 @@ cp_parser_pragma (cp_parser *parser, enu
case PRAGMA_OMP_ORDERED:
case PRAGMA_OMP_PARALLEL:
case PRAGMA_OMP_SECTIONS:
+ case PRAGMA_OMP_SIMD:
case PRAGMA_OMP_SINGLE:
case PRAGMA_OMP_TASK:
if (context == pragma_external)
@@ -13198,6 +13198,9 @@ tsubst_expr (tree t, tree args, tsubst_f
break;
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_FOR_SIMD:
+ case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;
tree declv, initv, condv, incrv;
@@ -13225,8 +13228,8 @@ tsubst_expr (tree t, tree args, tsubst_f
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv,
- body, pre_body, clauses);
+ t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv,
+ condv, incrv, body, pre_body, clauses);
add_stmt (finish_omp_structured_block (stmt));
}
@@ -314,11 +314,20 @@ dump_omp_clause (pretty_printer *buffer,
case OMP_CLAUSE_COPYPRIVATE:
name = "copyprivate";
goto print_remap;
+ case OMP_CLAUSE_FROM:
+ name = "from";
+ goto print_remap;
+ case OMP_CLAUSE_TO:
+ name = "to";
+ goto print_remap;
+ case OMP_CLAUSE_UNIFORM:
+ name = "uniform";
+ goto print_remap;
print_remap:
pp_string (buffer, name);
pp_character (buffer, '(');
dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
- spc, flags, false);
+ spc, flags, false);
pp_character (buffer, ')');
break;
@@ -327,21 +336,21 @@ dump_omp_clause (pretty_printer *buffer,
pp_string (buffer, op_symbol_code (OMP_CLAUSE_REDUCTION_CODE (clause)));
pp_character (buffer, ':');
dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
- spc, flags, false);
+ spc, flags, false);
pp_character (buffer, ')');
break;
case OMP_CLAUSE_IF:
pp_string (buffer, "if(");
dump_generic_node (buffer, OMP_CLAUSE_IF_EXPR (clause),
- spc, flags, false);
+ spc, flags, false);
pp_character (buffer, ')');
break;
case OMP_CLAUSE_NUM_THREADS:
pp_string (buffer, "num_threads(");
dump_generic_node (buffer, OMP_CLAUSE_NUM_THREADS_EXPR (clause),
- spc, flags, false);
+ spc, flags, false);
pp_character (buffer, ')');
break;
@@ -380,30 +389,29 @@ dump_omp_clause (pretty_printer *buffer,
pp_string (buffer, "schedule(");
switch (OMP_CLAUSE_SCHEDULE_KIND (clause))
{
- case OMP_CLAUSE_SCHEDULE_STATIC:
- pp_string (buffer, "static");
- break;
- case OMP_CLAUSE_SCHEDULE_DYNAMIC:
- pp_string (buffer, "dynamic");
- break;
- case OMP_CLAUSE_SCHEDULE_GUIDED:
- pp_string (buffer, "guided");
- break;
- case OMP_CLAUSE_SCHEDULE_RUNTIME:
- pp_string (buffer, "runtime");
- break;
- case OMP_CLAUSE_SCHEDULE_AUTO:
- pp_string (buffer, "auto");
- break;
- default:
- gcc_unreachable ();
+ case OMP_CLAUSE_SCHEDULE_STATIC:
+ pp_string (buffer, "static");
+ break;
+ case OMP_CLAUSE_SCHEDULE_DYNAMIC:
+ pp_string (buffer, "dynamic");
+ break;
+ case OMP_CLAUSE_SCHEDULE_GUIDED:
+ pp_string (buffer, "guided");
+ break;
+ case OMP_CLAUSE_SCHEDULE_RUNTIME:
+ pp_string (buffer, "runtime");
+ break;
+ case OMP_CLAUSE_SCHEDULE_AUTO:
+ pp_string (buffer, "auto");
+ break;
+ default:
+ gcc_unreachable ();
}
if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause))
{
pp_character (buffer, ',');
- dump_generic_node (buffer,
- OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause),
- spc, flags, false);
+ dump_generic_node (buffer, OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause),
+ spc, flags, false);
}
pp_character (buffer, ')');
break;
@@ -414,8 +422,7 @@ dump_omp_clause (pretty_printer *buffer,
case OMP_CLAUSE_COLLAPSE:
pp_string (buffer, "collapse(");
- dump_generic_node (buffer,
- OMP_CLAUSE_COLLAPSE_EXPR (clause),
+ dump_generic_node (buffer, OMP_CLAUSE_COLLAPSE_EXPR (clause),
spc, flags, false);
pp_character (buffer, ')');
break;
@@ -423,7 +430,7 @@ dump_omp_clause (pretty_printer *buffer,
case OMP_CLAUSE_FINAL:
pp_string (buffer, "final(");
dump_generic_node (buffer, OMP_CLAUSE_FINAL_EXPR (clause),
- spc, flags, false);
+ spc, flags, false);
pp_character (buffer, ')');
break;
@@ -431,6 +438,154 @@ dump_omp_clause (pretty_printer *buffer,
pp_string (buffer, "mergeable");
break;
+ case OMP_CLAUSE_LINEAR:
+ pp_string (buffer, "linear(");
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ pp_character (buffer, ':');
+ dump_generic_node (buffer, OMP_CLAUSE_LINEAR_STEP (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_ALIGNED:
+ pp_string (buffer, "aligned(");
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+ {
+ pp_character (buffer, ':');
+ dump_generic_node (buffer, OMP_CLAUSE_ALIGNED_ALIGNMENT (clause),
+ spc, flags, false);
+ }
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_DEPEND:
+ pp_string (buffer, "depend(");
+ switch (OMP_CLAUSE_DEPEND_KIND (clause))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ pp_string (buffer, "in");
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ pp_string (buffer, "out");
+ break;
+ case OMP_CLAUSE_DEPEND_INOUT:
+ pp_string (buffer, "inout");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ pp_character (buffer, ':');
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_MAP:
+ pp_string (buffer, "map(");
+ switch (OMP_CLAUSE_MAP_KIND (clause))
+ {
+ case OMP_CLAUSE_MAP_ALLOC:
+ pp_string (buffer, "alloc");
+ break;
+ case OMP_CLAUSE_MAP_TO:
+ pp_string (buffer, "to");
+ break;
+ case OMP_CLAUSE_MAP_FROM:
+ pp_string (buffer, "from");
+ break;
+ case OMP_CLAUSE_MAP_TOFROM:
+ pp_string (buffer, "tofrom");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ pp_character (buffer, ':');
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_NUM_TEAMS:
+ pp_string (buffer, "num_teams(");
+ dump_generic_node (buffer, OMP_CLAUSE_NUM_TEAMS_EXPR (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_DEVICE:
+ pp_string (buffer, "device(");
+ dump_generic_node (buffer, OMP_CLAUSE_DEVICE_ID (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ pp_string (buffer, "dist_schedule(static");
+ if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause))
+ {
+ pp_character (buffer, ',');
+ dump_generic_node (buffer,
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause),
+ spc, flags, false);
+ }
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_PROC_BIND:
+ pp_string (buffer, "proc_bind(");
+ switch (OMP_CLAUSE_PROC_BIND_KIND (clause))
+ {
+ case OMP_CLAUSE_PROC_BIND_MASTER:
+ pp_string (buffer, "master");
+ break;
+ case OMP_CLAUSE_PROC_BIND_CLOSE:
+ pp_string (buffer, "close");
+ break;
+ case OMP_CLAUSE_PROC_BIND_SPREAD:
+ pp_string (buffer, "spread");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_SAFELEN:
+ pp_string (buffer, "safelen(");
+ dump_generic_node (buffer, OMP_CLAUSE_SAFELEN_EXPR (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_SIMDLEN:
+ pp_string (buffer, "simdlen(");
+ dump_generic_node (buffer, OMP_CLAUSE_SIMDLEN_EXPR (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_INBRANCH:
+ pp_string (buffer, "inbranch");
+ break;
+ case OMP_CLAUSE_NOTINBRANCH:
+ pp_string (buffer, "notinbranch");
+ break;
+ case OMP_CLAUSE_FOR:
+ pp_string (buffer, "for");
+ break;
+ case OMP_CLAUSE_PARALLEL:
+ pp_string (buffer, "parallel");
+ break;
+ case OMP_CLAUSE_SECTIONS:
+ pp_string (buffer, "sections");
+ break;
+ case OMP_CLAUSE_TASKGROUP:
+ pp_string (buffer, "taskgroup");
+ break;
+
default:
/* Should never happen. */
dump_generic_node (buffer, clause, spc, flags, false);
@@ -2178,6 +2333,21 @@ dump_generic_node (pretty_printer *buffe
case OMP_FOR:
pp_string (buffer, "#pragma omp for");
+ goto dump_omp_loop;
+
+ case OMP_SIMD:
+ pp_string (buffer, "#pragma omp simd");
+ goto dump_omp_loop;
+
+ case OMP_FOR_SIMD:
+ pp_string (buffer, "#pragma omp for simd");
+ goto dump_omp_loop;
+
+ case OMP_DISTRIBUTE:
+ pp_string (buffer, "#pragma omp distribute");
+ goto dump_omp_loop;
+
+ dump_omp_loop:
dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags);
if (!(flags & TDF_SLIM))
@@ -361,6 +361,27 @@ enum omp_clause_code
/* OpenMP clause: copyprivate (variable_list). */
OMP_CLAUSE_COPYPRIVATE,
+ /* OpenMP clause: linear (variable-list[:linear-step]). */
+ OMP_CLAUSE_LINEAR,
+
+ /* OpenMP clause: aligned (variable-list[:alignment]). */
+ OMP_CLAUSE_ALIGNED,
+
+ /* OpenMP clause: depend ({in,out,inout}:variable-list). */
+ OMP_CLAUSE_DEPEND,
+
+ /* OpenMP clause: from (variable-list). */
+ OMP_CLAUSE_FROM,
+
+ /* OpenMP clause: to (variable-list). */
+ OMP_CLAUSE_TO,
+
+ /* OpenMP clause: uniform (argument-list). */
+ OMP_CLAUSE_UNIFORM,
+
+ /* OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */
+ OMP_CLAUSE_MAP,
+
/* OpenMP clause: if (scalar-expression). */
OMP_CLAUSE_IF,
@@ -389,7 +410,43 @@ enum omp_clause_code
OMP_CLAUSE_FINAL,
/* OpenMP clause: mergeable. */
- OMP_CLAUSE_MERGEABLE
+ OMP_CLAUSE_MERGEABLE,
+
+ /* OpenMP clause: device (integer-expression). */
+ OMP_CLAUSE_DEVICE,
+
+ /* OpenMP clause: dist_schedule (static[:chunk-size]). */
+ OMP_CLAUSE_DIST_SCHEDULE,
+
+ /* OpenMP clause: inbranch. */
+ OMP_CLAUSE_INBRANCH,
+
+ /* OpenMP clause: notinbranch. */
+ OMP_CLAUSE_NOTINBRANCH,
+
+ /* OpenMP clause: num_teams(integer-expression). */
+ OMP_CLAUSE_NUM_TEAMS,
+
+ /* OpenMP clause: proc_bind ({master,close,spread}). */
+ OMP_CLAUSE_PROC_BIND,
+
+ /* OpenMP clause: safelen (constant-integer-expression). */
+ OMP_CLAUSE_SAFELEN,
+
+ /* OpenMP clause: simdlen (constant-integer-expression). */
+ OMP_CLAUSE_SIMDLEN,
+
+ /* OpenMP clause: for. */
+ OMP_CLAUSE_FOR,
+
+ /* OpenMP clause: parallel. */
+ OMP_CLAUSE_PARALLEL,
+
+ /* OpenMP clause: sections. */
+ OMP_CLAUSE_SECTIONS,
+
+ /* OpenMP clause: taskgroup. */
+ OMP_CLAUSE_TASKGROUP
};
/* The definition of tree nodes fills the next several pages. */
@@ -1766,12 +1823,13 @@ extern void protected_set_expr_location
#define OMP_TASKREG_BODY(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 0)
#define OMP_TASKREG_CLAUSES(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 1)
-#define OMP_FOR_BODY(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 0)
-#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 1)
-#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 2)
-#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 3)
-#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 4)
-#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 5)
+#define OMP_LOOP_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_FOR, OMP_DISTRIBUTE)
+#define OMP_FOR_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 0)
+#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 1)
+#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 2)
+#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 3)
+#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 4)
+#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 5)
#define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
#define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)
@@ -1792,7 +1850,7 @@ extern void protected_set_expr_location
#define OMP_CLAUSE_DECL(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
OMP_CLAUSE_PRIVATE, \
- OMP_CLAUSE_COPYPRIVATE), 0)
+ OMP_CLAUSE_MAP), 0)
#define OMP_CLAUSE_HAS_LOCATION(NODE) \
(LOCATION_LOCUS ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus) \
!= UNKNOWN_LOCATION)
@@ -1859,6 +1917,28 @@ extern void protected_set_expr_location
#define OMP_CLAUSE_REDUCTION_PLACEHOLDER(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 3)
+#define OMP_CLAUSE_LINEAR_STEP(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1)
+
+#define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1)
+
+#define OMP_CLAUSE_NUM_TEAMS_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TEAMS), 0)
+
+#define OMP_CLAUSE_DEVICE_ID(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEVICE), 0)
+
+#define OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE_DIST_SCHEDULE), 0)
+
+#define OMP_CLAUSE_SAFELEN_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SAFELEN), 0)
+
+#define OMP_CLAUSE_SIMDLEN_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SIMDLEN), 0)
+
enum omp_clause_schedule_kind
{
OMP_CLAUSE_SCHEDULE_STATIC,
@@ -1883,6 +1963,40 @@ enum omp_clause_default_kind
#define OMP_CLAUSE_DEFAULT_KIND(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEFAULT)->omp_clause.subcode.default_kind)
+enum omp_clause_depend_kind
+{
+ OMP_CLAUSE_DEPEND_IN,
+ OMP_CLAUSE_DEPEND_OUT,
+ OMP_CLAUSE_DEPEND_INOUT
+};
+
+#define OMP_CLAUSE_DEPEND_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind)
+
+enum omp_clause_map_kind
+{
+ OMP_CLAUSE_MAP_ALLOC,
+ OMP_CLAUSE_MAP_TO,
+ OMP_CLAUSE_MAP_FROM,
+ OMP_CLAUSE_MAP_TOFROM
+};
+
+#define OMP_CLAUSE_MAP_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind)
+
+enum omp_clause_proc_bind_kind
+{
+ /* Numbers should match omp_proc_bind_t enum in omp.h. */
+ OMP_CLAUSE_PROC_BIND_FALSE = 0,
+ OMP_CLAUSE_PROC_BIND_TRUE = 1,
+ OMP_CLAUSE_PROC_BIND_MASTER = 2,
+ OMP_CLAUSE_PROC_BIND_CLOSE = 3,
+ OMP_CLAUSE_PROC_BIND_SPREAD = 4
+};
+
+#define OMP_CLAUSE_PROC_BIND_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PROC_BIND)->omp_clause.subcode.proc_bind_kind)
+
struct GTY(()) tree_exp {
struct tree_typed typed;
location_t locus;
@@ -2006,9 +2120,12 @@ struct GTY(()) tree_omp_clause {
location_t locus;
enum omp_clause_code code;
union omp_clause_subcode {
- enum omp_clause_default_kind default_kind;
- enum omp_clause_schedule_kind schedule_kind;
- enum tree_code reduction_code;
+ enum omp_clause_default_kind default_kind;
+ enum omp_clause_schedule_kind schedule_kind;
+ enum omp_clause_depend_kind depend_kind;
+ enum omp_clause_map_kind map_kind;
+ enum omp_clause_proc_bind_kind proc_bind_kind;
+ enum tree_code reduction_code;
} GTY ((skip)) subcode;
/* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's
@@ -4774,6 +4891,7 @@ extern tree build_translation_unit_decl
extern tree build_block (tree, tree, tree, tree);
extern tree build_empty_stmt (location_t);
extern tree build_omp_clause (location_t, enum omp_clause_code);
+extern tree find_omp_clause (tree, enum omp_clause_code);
extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
#define build_vl_exp(c,n) build_vl_exp_stat (c,n MEM_STAT_INFO)
@@ -39,6 +39,10 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKYIELD, "GOMP_taskyield",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CANCEL, "GOMP_cancel",
+ BT_FN_VOID_INT, ATTR_NULL)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CANCELLATION_POINT, "GOMP_cancellation_point",
+ BT_FN_VOID_INT, ATTR_NULL)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_START, "GOMP_critical_start",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_END, "GOMP_critical_end",
@@ -350,7 +350,6 @@ extern struct omp_region *new_omp_region
struct omp_region *);
extern void free_omp_regions (void);
void omp_expand_local (basic_block);
-extern tree find_omp_clause (tree, enum omp_clause_code);
tree copy_var_decl (tree, tree, tree);
/*---------------------------------------------------------------------------
@@ -343,8 +343,8 @@ check_omp_for_incr_expr (location_t loc,
the loop. */
tree
-c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
- tree incrv, tree body, tree pre_body)
+c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
+ tree initv, tree condv, tree incrv, tree body, tree pre_body)
{
location_t elocus;
bool fail = false;
@@ -569,7 +569,7 @@ c_finish_omp_for (location_t locus, tree
return NULL;
else
{
- tree t = make_node (OMP_FOR);
+ tree t = make_node (code);
TREE_TYPE (t) = void_type_node;
OMP_FOR_INIT (t) = initv;
@@ -621,6 +621,9 @@ c_split_parallel_clauses (location_t loc
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_LINEAR:
OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
*ws_clauses = clauses;
break;
@@ -29,21 +29,36 @@ typedef enum pragma_kind {
PRAGMA_OMP_ATOMIC,
PRAGMA_OMP_BARRIER,
+ PRAGMA_OMP_CANCEL,
+ PRAGMA_OMP_CANCELLATION_POINT,
PRAGMA_OMP_CRITICAL,
+ PRAGMA_OMP_DECLARE_REDUCTION,
+ PRAGMA_OMP_DECLARE_SIMD,
+ PRAGMA_OMP_DECLARE_TARGET,
+ PRAGMA_OMP_DISTRIBUTE,
+ PRAGMA_OMP_END_DECLARE_TARGET,
PRAGMA_OMP_FLUSH,
PRAGMA_OMP_FOR,
+ PRAGMA_OMP_FOR_SIMD,
PRAGMA_OMP_MASTER,
PRAGMA_OMP_ORDERED,
PRAGMA_OMP_PARALLEL,
PRAGMA_OMP_PARALLEL_FOR,
+ PRAGMA_OMP_PARALLEL_FOR_SIMD,
PRAGMA_OMP_PARALLEL_SECTIONS,
PRAGMA_OMP_SECTION,
PRAGMA_OMP_SECTIONS,
+ PRAGMA_OMP_SIMD,
PRAGMA_OMP_SINGLE,
+ PRAGMA_OMP_TARGET,
+ PRAGMA_OMP_TARGET_DATA,
+ PRAGMA_OMP_TARGET_UPDATE,
PRAGMA_OMP_TASK,
+ PRAGMA_OMP_TASKGROUP,
PRAGMA_OMP_TASKWAIT,
PRAGMA_OMP_TASKYIELD,
PRAGMA_OMP_THREADPRIVATE,
+ PRAGMA_OMP_TEAMS,
PRAGMA_GCC_PCH_PREPROCESS,
@@ -51,28 +66,47 @@ typedef enum pragma_kind {
} pragma_kind;
-/* All clauses defined by OpenMP 2.5 and 3.0.
+/* All clauses defined by OpenMP 2.5, 3.0, 3.1 and 4.0.
Used internally by both C and C++ parsers. */
typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_NONE = 0,
+ PRAGMA_OMP_CLAUSE_ALIGNED,
PRAGMA_OMP_CLAUSE_COLLAPSE,
PRAGMA_OMP_CLAUSE_COPYIN,
PRAGMA_OMP_CLAUSE_COPYPRIVATE,
PRAGMA_OMP_CLAUSE_DEFAULT,
+ PRAGMA_OMP_CLAUSE_DEPEND,
+ PRAGMA_OMP_CLAUSE_DEVICE,
+ PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_FINAL,
PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
+ PRAGMA_OMP_CLAUSE_FOR,
+ PRAGMA_OMP_CLAUSE_FROM,
PRAGMA_OMP_CLAUSE_IF,
+ PRAGMA_OMP_CLAUSE_INBRANCH,
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
+ PRAGMA_OMP_CLAUSE_LINEAR,
+ PRAGMA_OMP_CLAUSE_MAP,
+ PRAGMA_OMP_CLAUSE_MERGEABLE,
+ PRAGMA_OMP_CLAUSE_NOTINBRANCH,
PRAGMA_OMP_CLAUSE_NOWAIT,
+ PRAGMA_OMP_CLAUSE_NUM_TEAMS,
PRAGMA_OMP_CLAUSE_NUM_THREADS,
PRAGMA_OMP_CLAUSE_ORDERED,
+ PRAGMA_OMP_CLAUSE_PARALLEL,
PRAGMA_OMP_CLAUSE_PRIVATE,
+ PRAGMA_OMP_CLAUSE_PROC_BIND,
PRAGMA_OMP_CLAUSE_REDUCTION,
+ PRAGMA_OMP_CLAUSE_SAFELEN,
PRAGMA_OMP_CLAUSE_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_SECTIONS,
PRAGMA_OMP_CLAUSE_SHARED,
- PRAGMA_OMP_CLAUSE_UNTIED,
- PRAGMA_OMP_CLAUSE_FINAL,
- PRAGMA_OMP_CLAUSE_MERGEABLE
+ PRAGMA_OMP_CLAUSE_SIMDLEN,
+ PRAGMA_OMP_CLAUSE_TASKGROUP,
+ PRAGMA_OMP_CLAUSE_TO,
+ PRAGMA_OMP_CLAUSE_UNIFORM,
+ PRAGMA_OMP_CLAUSE_UNTIED
} pragma_omp_clause;
extern struct cpp_reader* parse_in;
@@ -1162,7 +1162,11 @@ struct omp_pragma_def { const char *name
static const struct omp_pragma_def omp_pragmas[] = {
{ "atomic", PRAGMA_OMP_ATOMIC },
{ "barrier", PRAGMA_OMP_BARRIER },
+ { "cancel", PRAGMA_OMP_CANCEL },
+ { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
{ "critical", PRAGMA_OMP_CRITICAL },
+ { "declare", PRAGMA_OMP_DECLARE_REDUCTION },
+ { "end", PRAGMA_OMP_END_DECLARE_TARGET },
{ "flush", PRAGMA_OMP_FLUSH },
{ "for", PRAGMA_OMP_FOR },
{ "master", PRAGMA_OMP_MASTER },
@@ -1170,10 +1174,14 @@ static const struct omp_pragma_def omp_p
{ "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 }
};
@@ -1039,7 +1039,8 @@ extern tree c_finish_omp_atomic (locatio
extern void c_finish_omp_flush (location_t);
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
-extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
+extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
+ tree, tree, tree);
extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
@@ -1133,4 +1134,129 @@ enum stv_conv {
extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
tree op0, tree op1, bool);
+#if HOST_BITS_PER_WIDE_INT >= 64
+typedef unsigned HOST_WIDE_INT omp_clause_mask;
+# define OMP_CLAUSE_MASK_1 ((omp_clause_mask) 1)
+#else
+struct omp_clause_mask
+{
+ inline omp_clause_mask ();
+ inline omp_clause_mask (unsigned HOST_WIDE_INT l);
+ inline omp_clause_mask (unsigned HOST_WIDE_INT l,
+ unsigned HOST_WIDE_INT h);
+ inline omp_clause_mask &operator &= (omp_clause_mask);
+ inline omp_clause_mask &operator |= (omp_clause_mask);
+ inline omp_clause_mask operator ~ () const;
+ inline omp_clause_mask operator & (omp_clause_mask) const;
+ inline omp_clause_mask operator | (omp_clause_mask) const;
+ inline omp_clause_mask operator >> (int);
+ inline omp_clause_mask operator << (int);
+ inline bool operator == (omp_clause_mask) const;
+ unsigned HOST_WIDE_INT low, high;
+};
+
+inline
+omp_clause_mask::omp_clause_mask ()
+{
+}
+
+inline
+omp_clause_mask::omp_clause_mask (unsigned HOST_WIDE_INT l)
+: low (l), high (0)
+{
+}
+
+inline
+omp_clause_mask::omp_clause_mask (unsigned HOST_WIDE_INT l,
+ unsigned HOST_WIDE_INT h)
+: low (l), high (h)
+{
+}
+
+inline omp_clause_mask &
+omp_clause_mask::operator &= (omp_clause_mask b)
+{
+ low &= b.low;
+ high &= b.high;
+ return *this;
+}
+
+inline omp_clause_mask &
+omp_clause_mask::operator |= (omp_clause_mask b)
+{
+ low |= b.low;
+ high |= b.high;
+ return *this;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator ~ () const
+{
+ omp_clause_mask ret (~low, ~high);
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator | (omp_clause_mask b) const
+{
+ omp_clause_mask ret (low | b.low, high | b.high);
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator & (omp_clause_mask b) const
+{
+ omp_clause_mask ret (low & b.low, high & b.high);
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator << (int amount)
+{
+ omp_clause_mask ret;
+ if (amount >= HOST_BITS_PER_WIDE_INT)
+ {
+ ret.low = 0;
+ ret.high = low << (amount - HOST_BITS_PER_WIDE_INT);
+ }
+ else if (amount == 0)
+ ret = *this;
+ else
+ {
+ ret.low = low << amount;
+ ret.high = (low >> (HOST_BITS_PER_WIDE_INT - amount))
+ | (high << amount);
+ }
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator >> (int amount)
+{
+ omp_clause_mask ret;
+ if (amount >= HOST_BITS_PER_WIDE_INT)
+ {
+ ret.low = high >> (amount - HOST_BITS_PER_WIDE_INT);
+ ret.high = 0;
+ }
+ else if (amount == 0)
+ ret = *this;
+ else
+ {
+ ret.low = (high << (HOST_BITS_PER_WIDE_INT - amount))
+ | (low >> amount);
+ ret.high = high >> amount;
+ }
+ return ret;
+}
+
+inline bool
+omp_clause_mask::operator == (omp_clause_mask b) const
+{
+ return low == b.low && high == b.high;
+}
+
+# define OMP_CLAUSE_MASK_1 omp_clause_mask (1)
+#endif
+
#endif /* ! GCC_C_COMMON_H */