@@ -1110,9 +1110,6 @@ dump_gimple_omp_for (pretty_printer *buf
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;
@@ -1144,9 +1141,6 @@ dump_gimple_omp_for (pretty_printer *buf
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;
@@ -11044,7 +11044,7 @@ c_parser_omp_for (location_t loc, c_pars
if (strcmp (p, "simd") == 0)
{
c_parser_consume_token (parser);
- code = OMP_FOR_SIMD;
+ /* code = OMP_FOR_SIMD; */
mask |= OMP_SIMD_CLAUSE_MASK;
p_name = "#pragma omp for simd";
}
@@ -11234,6 +11234,7 @@ c_parser_omp_parallel (location_t loc, c
const char *p_name = "#pragma omp parallel";
tree stmt, clauses, par_clause, ws_clause, block;
omp_clause_mask mask = OMP_PARALLEL_CLAUSE_MASK;
+ tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
@@ -11280,7 +11281,9 @@ c_parser_omp_parallel (location_t loc, c
case PRAGMA_OMP_PARALLEL_FOR:
block = c_begin_omp_parallel ();
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+ c_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+ par_clause = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ ws_clause = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
c_parser_omp_for_loop (loc, parser, OMP_FOR, ws_clause, &par_clause);
stmt = c_finish_omp_parallel (loc, par_clause, block);
OMP_PARALLEL_COMBINED (stmt) = 1;
@@ -11288,8 +11291,10 @@ c_parser_omp_parallel (location_t loc, c
case PRAGMA_OMP_PARALLEL_FOR_SIMD:
block = c_begin_omp_parallel ();
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- c_parser_omp_for_loop (loc, parser, OMP_FOR_SIMD, ws_clause,
+ c_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+ par_clause = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ ws_clause = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ c_parser_omp_for_loop (loc, parser, OMP_FOR /*_SIMD*/, ws_clause,
&par_clause);
stmt = c_finish_omp_parallel (loc, par_clause, block);
OMP_PARALLEL_COMBINED (stmt) = 1;
@@ -11297,7 +11302,9 @@ c_parser_omp_parallel (location_t loc, c
case PRAGMA_OMP_PARALLEL_SECTIONS:
block = c_begin_omp_parallel ();
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+ c_omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+ par_clause = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ ws_clause = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
stmt = c_parser_omp_sections_scope (loc, parser);
if (stmt)
OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
@@ -27299,7 +27299,8 @@ cp_parser_omp_clause_proc_bind (cp_parse
static tree
cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
- const char *where, cp_token *pragma_tok)
+ const char *where, cp_token *pragma_tok,
+ bool finish_p = true)
{
tree clauses = NULL;
bool first = true;
@@ -27526,9 +27527,9 @@ cp_parser_omp_all_clauses (cp_parser *pa
}
saw_error:
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
- if (parser->omp_declare_simd_clauses)
- return clauses;
- return finish_omp_clauses (clauses);
+ if (finish_p)
+ return finish_omp_clauses (clauses);
+ return clauses;
}
/* OpenMP 2.5:
@@ -28202,7 +28203,7 @@ cp_parser_omp_for_incr (cp_parser *parse
static tree
cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
- tree *par_clauses)
+ tree *cclauses)
{
tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
tree real_decl, initv, condv, incrv, declv;
@@ -28412,10 +28413,12 @@ cp_parser_omp_for_loop (cp_parser *parse
if (decl)
real_decl = decl;
- if (par_clauses != NULL && real_decl != NULL_TREE)
+ if (cclauses != NULL
+ && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL
+ && real_decl != NULL_TREE)
{
tree *c;
- for (c = par_clauses; *c ; )
+ for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
&& OMP_CLAUSE_DECL (*c) == real_decl)
{
@@ -28594,6 +28597,20 @@ cp_parser_omp_for_loop (cp_parser *parse
return ret;
}
+/* Helper function for OpenMP parsing, split clauses and call
+ finish_omp_clauses on each of the set of clauses afterwards. */
+
+static void
+cp_omp_split_clauses (location_t loc, enum tree_code code,
+ omp_clause_mask mask, tree clauses, tree *cclauses)
+{
+ int i;
+ c_omp_split_clauses (loc, code, mask, clauses, cclauses);
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ if (cclauses[i])
+ cclauses[i] = finish_omp_clauses (cclauses[i]);
+}
+
/* OpenMP 4.0:
#pragma omp simd simd-clause[optseq] new-line
for-loop */
@@ -28608,18 +28625,29 @@ cp_parser_omp_for_loop (cp_parser *parse
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
-cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree clauses, sb, ret;
unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- clauses = cp_parser_omp_all_clauses (parser, OMP_SIMD_CLAUSE_MASK,
- "#pragma omp simd", pragma_tok);
+ strcat (p_name, " simd");
+ mask |= OMP_SIMD_CLAUSE_MASK;
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ }
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, NULL);
+ ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -28646,13 +28674,17 @@ cp_parser_omp_simd (cp_parser *parser, c
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
-cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
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";
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " for");
+ mask |= OMP_FOR_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -28661,19 +28693,41 @@ cp_parser_omp_for (cp_parser *parser, cp
if (strcmp (p, "simd") == 0)
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
cp_lexer_consume_token (parser->lexer);
- code = OMP_FOR_SIMD;
- mask |= OMP_SIMD_CLAUSE_MASK;
- p_name = "#pragma omp for simd";
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+ cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ ret = make_node (OMP_FOR);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = body;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
}
}
- clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok);
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ }
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, code, clauses, NULL);
+ ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -28800,12 +28854,24 @@ cp_parser_omp_sections_scope (cp_parser
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree clauses, ret;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- clauses = cp_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
- "#pragma omp sections", pragma_tok);
+ strcat (p_name, " sections");
+ mask |= OMP_SECTIONS_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
+ }
ret = cp_parser_omp_sections_scope (parser);
if (ret)
@@ -28834,35 +28900,37 @@ cp_parser_omp_sections (cp_parser *parse
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
-cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
- enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
- const char *p_name = "#pragma omp parallel";
- tree stmt, clauses, par_clause, ws_clause, block;
- omp_clause_mask mask = OMP_PARALLEL_CLAUSE_MASK;
+ tree stmt, clauses, block;
unsigned int save;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ strcat (p_name, " parallel");
+ mask |= OMP_PARALLEL_CLAUSE_MASK;
+
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
{
- cp_lexer_consume_token (parser->lexer);
- p_kind = PRAGMA_OMP_PARALLEL_FOR;
- p_name = "#pragma omp parallel for";
- mask |= OMP_FOR_CLAUSE_MASK;
- 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);
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
- 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;
- }
- }
+ cp_lexer_consume_token (parser->lexer);
+ 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_end_omp_structured_block (parser, save);
+ stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
+ }
+ else if (cclauses)
+ {
+ error_at (loc, "expected %<for%> after %qs", p_name);
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
}
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -28870,50 +28938,28 @@ cp_parser_omp_parallel (cp_parser *parse
const char *p = IDENTIFIER_POINTER (id);
if (strcmp (p, "sections") == 0)
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ cclauses = cclauses_buf;
+
cp_lexer_consume_token (parser->lexer);
- p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
- p_name = "#pragma omp parallel sections";
- mask |= OMP_SECTIONS_CLAUSE_MASK;
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+ block = begin_omp_parallel ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ cp_parser_omp_sections (parser, pragma_tok, p_name, mask, cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
}
}
clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok);
+
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
-
- switch (p_kind)
- {
- case PRAGMA_OMP_PARALLEL:
- cp_parser_statement (parser, NULL_TREE, false, NULL);
- par_clause = clauses;
- break;
-
- case PRAGMA_OMP_PARALLEL_FOR:
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_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:
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- stmt = cp_parser_omp_sections_scope (parser);
- if (stmt)
- OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
- break;
-
- default:
- gcc_unreachable ();
- }
-
+ cp_parser_statement (parser, NULL_TREE, false, NULL);
cp_parser_end_omp_structured_block (parser, save);
- stmt = finish_omp_parallel (par_clause, block);
- if (p_kind != PRAGMA_OMP_PARALLEL)
- OMP_PARALLEL_COMBINED (stmt) = 1;
+ stmt = finish_omp_parallel (clauses, block);
return stmt;
}
@@ -29088,6 +29134,92 @@ cp_parser_omp_cancellation_point (cp_par
}
/* OpenMP 4.0:
+ #pragma omp distribute distribute-clause[optseq] new-line
+ for-loop */
+
+#define OMP_DISTRIBUTE_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_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " distribute");
+ mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
+
+ 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);
+ bool simd = false;
+ bool parallel = false;
+
+ if (strcmp (p, "simd") == 0)
+ {
+ simd = true;
+ if (cclauses)
+ {
+ error_at (loc, "%<simd%> not expected after %qs", p_name);
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+ }
+ else
+ parallel = strcmp (p, "parallel") == 0;
+ if (parallel || simd)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ if (simd)
+ ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+ cclauses);
+ else
+ ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
+ cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ ret = make_node (OMP_DISTRIBUTE);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = body;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
+ }
+ }
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ }
+
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+
+ ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL);
+
+ cp_parser_end_omp_structured_block (parser, save);
+ add_stmt (finish_omp_structured_block (sb));
+
+ return ret;
+}
+
+/* OpenMP 4.0:
# pragma omp teams teams-clause[optseq] new-line
structured-block */
@@ -29101,14 +29233,55 @@ cp_parser_omp_cancellation_point (cp_par
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
static tree
-cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " teams");
+ mask |= OMP_TEAMS_CLAUSE_MASK;
+
+ 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, "distribute") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ cp_lexer_consume_token (parser->lexer);
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
+ cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ ret = make_node (OMP_TEAMS);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_TEAMS_CLAUSES (ret) = clauses;
+ OMP_TEAMS_BODY (ret) = body;
+ return add_stmt (ret);
+ }
+ }
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ }
+
tree stmt = make_node (OMP_TEAMS);
TREE_TYPE (stmt) = void_type_node;
-
- OMP_TEAMS_CLAUSES (stmt)
- = cp_parser_omp_all_clauses (parser, OMP_TEAMS_CLAUSE_MASK,
- "#pragma omp teams", pragma_tok);
+ OMP_TEAMS_CLAUSES (stmt) = clauses;
OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser);
return add_stmt (stmt);
@@ -29216,6 +29389,29 @@ cp_parser_omp_target (cp_parser *parser,
cp_lexer_consume_token (parser->lexer);
return cp_parser_omp_target_update (parser, pragma_tok, context);
}
+ else if (strcmp (p, "teams") == 0)
+ {
+ tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+ char p_name[sizeof ("#pragma omp target teams distribute "
+ "parallel for simd")];
+
+ cp_lexer_consume_token (parser->lexer);
+ strcpy (p_name, "#pragma omp target");
+ 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,
+ OMP_TARGET_CLAUSE_MASK, cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ tree stmt = make_node (OMP_TARGET);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
+ OMP_TARGET_BODY (stmt) = body;
+ add_stmt (stmt);
+ return true;
+ }
}
tree stmt = make_node (OMP_TARGET);
@@ -29232,36 +29428,6 @@ cp_parser_omp_target (cp_parser *parser,
}
/* OpenMP 4.0:
- #pragma omp distribute distribute-clause[optseq] new-line
- for-loop */
-
-#define OMP_DISTRIBUTE_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_DIST_SCHEDULE)\
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
-
-static tree
-cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok)
-{
- tree clauses, sb, ret;
- unsigned int save;
-
- clauses = cp_parser_omp_all_clauses (parser, OMP_DISTRIBUTE_CLAUSE_MASK,
- "#pragma omp distribute", pragma_tok);
-
- sb = begin_omp_structured_block ();
- save = cp_parser_begin_omp_structured_block (parser);
-
- ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL);
-
- cp_parser_end_omp_structured_block (parser, save);
- add_stmt (finish_omp_structured_block (sb));
-
- return ret;
-}
-
-/* OpenMP 4.0:
# pragma omp declare simd declare-simd-clauses[optseq] new-line */
#define OMP_DECLARE_SIMD_CLAUSE_MASK \
@@ -29281,7 +29447,8 @@ cp_parser_omp_declare_simd (cp_parser *p
vec_safe_push (parser->omp_declare_simd_clauses, NULL_TREE);
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
- "#pragma omp declare simd", pragma_tok);
+ "#pragma omp declare simd", pragma_tok,
+ false);
parser->omp_declare_simd_clauses->last () = clauses;
if (first_p)
{
@@ -29382,6 +29549,8 @@ static void
cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
{
tree stmt;
+ char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
+ omp_clause_mask mask (0);
switch (pragma_tok->pragma_kind)
{
@@ -29392,10 +29561,12 @@ cp_parser_omp_construct (cp_parser *pars
stmt = cp_parser_omp_critical (parser, pragma_tok);
break;
case PRAGMA_OMP_DISTRIBUTE:
- stmt = cp_parser_omp_distribute (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_FOR:
- stmt = cp_parser_omp_for (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_MASTER:
stmt = cp_parser_omp_master (parser, pragma_tok);
@@ -29404,13 +29575,16 @@ cp_parser_omp_construct (cp_parser *pars
stmt = cp_parser_omp_ordered (parser, pragma_tok);
break;
case PRAGMA_OMP_PARALLEL:
- stmt = cp_parser_omp_parallel (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_SECTIONS:
- stmt = cp_parser_omp_sections (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_SIMD:
- stmt = cp_parser_omp_simd (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_SINGLE:
stmt = cp_parser_omp_single (parser, pragma_tok);
@@ -29422,7 +29596,8 @@ cp_parser_omp_construct (cp_parser *pars
cp_parser_omp_taskgroup (parser, pragma_tok);
return;
case PRAGMA_OMP_TEAMS:
- stmt = cp_parser_omp_teams (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL);
break;
default:
gcc_unreachable ();
@@ -13293,19 +13293,22 @@ tsubst_expr (tree t, tree args, tsubst_f
case OMP_FOR:
case OMP_SIMD:
- case OMP_FOR_SIMD:
case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;
- tree declv, initv, condv, incrv;
+ tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE;
+ tree incrv = NULL_TREE;
int i;
clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
args, complain, in_decl);
- declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ {
+ declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ }
stmt = begin_omp_structured_block ();
@@ -13313,17 +13316,29 @@ tsubst_expr (tree t, tree args, tsubst_f
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
- for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
- tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
- &clauses, args, complain, in_decl,
- integral_constant_expression_p);
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
+ &clauses, args, complain, in_decl,
+ integral_constant_expression_p);
body = push_stmt_list ();
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv,
- condv, incrv, body, pre_body, clauses);
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv,
+ condv, incrv, body, pre_body, clauses);
+ else
+ {
+ t = make_node (TREE_CODE (t));
+ TREE_TYPE (t) = void_type_node;
+ OMP_FOR_BODY (t) = body;
+ OMP_FOR_PRE_BODY (t) = pre_body;
+ OMP_FOR_CLAUSES (t) = clauses;
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (t));
+ add_stmt (t);
+ }
add_stmt (finish_omp_structured_block (stmt));
}
@@ -5760,11 +5782,10 @@ finish_omp_for (location_t locus, enum t
if (CLASS_TYPE_P (TREE_TYPE (decl)))
{
- if (code == OMP_SIMD || code == OMP_FOR_SIMD)
+ if (code == OMP_SIMD)
{
- error_at (elocus, "%<#pragma omp%s simd%> used with class "
- "iteration variable %qE",
- code == OMP_FOR_SIMD ? " for" : "", decl);
+ error_at (elocus, "%<#pragma omp simd%> used with class "
+ "iteration variable %qE", decl);
return NULL;
}
if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
@@ -60,8 +60,7 @@ 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_SIMD, OMP_FOR_SIMD
- and OMP_DISTRIBUTE)
+ OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD and OMP_DISTRIBUTE)
BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
@@ -670,7 +670,6 @@ cp_gimplify_expr (tree *expr_p, gimple_s
case OMP_FOR:
case OMP_SIMD:
- case OMP_FOR_SIMD:
case OMP_DISTRIBUTE:
ret = cp_gimplify_omp_for (expr_p, pre_p);
break;
@@ -1121,7 +1120,6 @@ cp_genericize_r (tree *stmt_p, int *walk
genericize_break_stmt (stmt_p);
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)
@@ -113,8 +113,8 @@ enum gf_mask {
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,
+ GF_OMP_FOR_KIND_DISTRIBUTE = 2 << 0,
+ GF_OMP_FOR_COMBINED = 4 << 0,
GF_OMP_TARGET_KIND_MASK = 3 << 0,
GF_OMP_TARGET_KIND_REGION = 0 << 0,
GF_OMP_TARGET_KIND_DATA = 1 << 0,
@@ -4003,6 +4003,31 @@ gimple_omp_for_set_kind (gimple g, int k
}
+/* Return true if OMP for statement G has the
+ GF_OMP_FOR_COMBINED flag set. */
+
+static inline bool
+gimple_omp_for_combined_p (const_gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ return (gimple_omp_subcode (g) & GF_OMP_FOR_COMBINED) != 0;
+}
+
+
+/* Set the GF_OMP_FOR_COMBINED field in G depending on the boolean
+ value of COMBINED_P. */
+
+static inline void
+gimple_omp_for_set_combined_p (gimple g, bool combined_p)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ if (combined_p)
+ g->gsbase.subcode |= GF_OMP_FOR_COMBINED;
+ else
+ g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED;
+}
+
+
/* Return the clauses associated with OMP_FOR GS. */
static inline tree
@@ -4716,7 +4716,6 @@ is_gimple_stmt (tree t)
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SIMD:
- case OMP_FOR_SIMD:
case OMP_DISTRIBUTE:
case OMP_SECTIONS:
case OMP_SECTION:
@@ -6826,12 +6825,39 @@ gimplify_omp_task (tree *expr_p, gimple_
*expr_p = NULL_TREE;
}
+/* Helper function of gimplify_omp_for, find OMP_FOR resp. OMP_SIMD
+ with non-NULL OMP_FOR_INIT. */
+
+static tree
+find_combined_omp_for (tree *tp, int *walk_subtrees, void *)
+{
+ *walk_subtrees = 0;
+ switch (TREE_CODE (*tp))
+ {
+ case OMP_FOR:
+ *walk_subtrees = 1;
+ /* FALLTHRU */
+ case OMP_SIMD:
+ if (OMP_FOR_INIT (*tp) != NULL_TREE)
+ return *tp;
+ break;
+ case BIND_EXPR:
+ case STATEMENT_LIST:
+ case OMP_PARALLEL:
+ *walk_subtrees = 1;
+ break;
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
/* Gimplify the gross structure of an OMP_FOR statement. */
static enum gimplify_status
gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
{
- tree for_stmt, decl, var, t;
+ tree for_stmt, orig_for_stmt, decl, var, t;
enum gimplify_status ret = GS_ALL_DONE;
enum gimplify_status tret;
gimple gfor;
@@ -6840,10 +6866,9 @@ gimplify_omp_for (tree *expr_p, gimple_s
bool simd;
bitmap has_decl_expr = NULL;
- for_stmt = *expr_p;
+ orig_for_stmt = for_stmt = *expr_p;
- simd = TREE_CODE (for_stmt) == OMP_SIMD
- || TREE_CODE (for_stmt) == OMP_FOR_SIMD;
+ simd = TREE_CODE (for_stmt) == OMP_SIMD;
gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
TREE_CODE (for_stmt) == OMP_SIMD
? ORT_SIMD : ORT_WORKSHARE);
@@ -6876,6 +6901,13 @@ gimplify_omp_for (tree *expr_p, gimple_s
gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
+ if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
+ {
+ for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), find_combined_omp_for,
+ NULL, NULL);
+ gcc_assert (for_stmt != NULL_TREE);
+ }
+
for_body = NULL;
gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
== TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
@@ -6891,12 +6923,14 @@ gimplify_omp_for (tree *expr_p, gimple_s
|| POINTER_TYPE_P (TREE_TYPE (decl)));
/* Make sure the iteration variable is private. */
- bool is_private = omp_is_private (gimplify_omp_ctxp, decl, simd);
tree c = NULL_TREE;
- if (simd)
+ if (orig_for_stmt != for_stmt)
+ /* Do this only on innermost construct for combined ones. */;
+ else if (simd)
{
splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
(splay_tree_key)decl);
+ omp_is_private (gimplify_omp_ctxp, decl, simd);
if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
omp_notice_variable (gimplify_omp_ctxp, decl, true);
else
@@ -6913,7 +6947,7 @@ gimplify_omp_for (tree *expr_p, gimple_s
GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
}
}
- else if (is_private)
+ else if (omp_is_private (gimplify_omp_ctxp, decl, simd))
omp_notice_variable (gimplify_omp_ctxp, decl, true);
else
omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
@@ -6921,7 +6955,9 @@ gimplify_omp_for (tree *expr_p, gimple_s
/* If DECL is not a gimple register, create a temporary variable to act
as an iteration counter. This is valid, since DECL cannot be
modified in the body of the loop. */
- if (!is_gimple_reg (decl))
+ if (orig_for_stmt != for_stmt)
+ var = decl;
+ else if (!is_gimple_reg (decl))
{
var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
TREE_OPERAND (t, 0) = var;
@@ -6954,6 +6990,8 @@ gimplify_omp_for (tree *expr_p, gimple_s
{
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ if (orig_for_stmt != for_stmt)
+ break;
t = build_int_cst (TREE_TYPE (decl), 1);
if (c)
OMP_CLAUSE_LINEAR_STEP (c) = t;
@@ -6964,6 +7002,8 @@ gimplify_omp_for (tree *expr_p, gimple_s
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
+ if (orig_for_stmt != for_stmt)
+ break;
t = build_int_cst (TREE_TYPE (decl), -1);
if (c)
OMP_CLAUSE_LINEAR_STEP (c) = t;
@@ -7020,7 +7060,8 @@ gimplify_omp_for (tree *expr_p, gimple_s
gcc_unreachable ();
}
- if (var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
+ if ((var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
+ && orig_for_stmt == for_stmt)
{
for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
@@ -7045,23 +7086,37 @@ gimplify_omp_for (tree *expr_p, gimple_s
BITMAP_FREE (has_decl_expr);
- gimplify_and_add (OMP_FOR_BODY (for_stmt), &for_body);
+ gimplify_and_add (OMP_FOR_BODY (orig_for_stmt), &for_body);
+
+ if (orig_for_stmt != for_stmt)
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
+ {
+ t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
+ decl = TREE_OPERAND (t, 0);
+ var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
+ omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
+ TREE_OPERAND (t, 0) = var;
+ t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
+ TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
+ TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
+ }
- gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
+ gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt));
int kind;
- switch (TREE_CODE (for_stmt))
+ switch (TREE_CODE (orig_for_stmt))
{
case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
- case OMP_FOR_SIMD: kind = GF_OMP_FOR_KIND_FOR_SIMD; break;
case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
default:
gcc_unreachable ();
}
- gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (for_stmt),
+ gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
for_pre_body);
+ if (orig_for_stmt != for_stmt)
+ gimple_omp_for_set_combined_p (gfor, true);
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
{
@@ -8057,7 +8112,6 @@ gimplify_expr (tree *expr_p, gimple_seq
case OMP_FOR:
case OMP_SIMD:
- case OMP_FOR_SIMD:
case OMP_DISTRIBUTE:
ret = gimplify_omp_for (expr_p, pre_p);
break;
@@ -1976,7 +1976,7 @@ c-family/c-lex.o : c-family/c-lex.c $(CO
$(CPPLIB_H) $(TARGET_H) $(TIMEVAR_H)
c-family/c-omp.o : c-family/c-omp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(C_COMMON_H) $(GIMPLE_H) langhooks.h
+ $(TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(GIMPLE_H) langhooks.h
CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@
c-family/c-opts.o : c-family/c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
@@ -938,17 +938,25 @@ build_outer_var_ref (tree var, omp_conte
bool by_ref = use_pointer_for_field (var, NULL);
x = build_receiver_ref (var, by_ref, ctx);
}
+ else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+ && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+ {
+ /* #pragma omp simd isn't a worksharing construct, and can reference even
+ private vars in its linear etc. clauses. */
+ x = NULL_TREE;
+ if (ctx->outer && is_taskreg_ctx (ctx))
+ x = lookup_decl (var, ctx->outer);
+ else if (ctx->outer)
+ x = maybe_lookup_decl (var, ctx->outer);
+ if (x == NULL_TREE)
+ x = var;
+ }
else if (ctx->outer)
x = lookup_decl (var, ctx->outer);
else if (is_reference (var))
/* This can happen with orphaned constructs. If var is reference, it is
possible it is shared and as such valid. */
x = var;
- else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
- /* #pragma omp simd isn't a worksharing construct, and can reference even
- private vars in its linear etc. clauses. */
- x = var;
else
gcc_unreachable ();
@@ -1877,8 +1885,7 @@ check_omp_nesting_restrictions (gimple s
if (ctx != NULL)
{
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
- || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR_SIMD))
+ && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
{
error_at (gimple_location (stmt),
"OpenMP constructs may not be nested inside simd region");
@@ -1034,10 +1034,6 @@ DEFTREECODE (OMP_FOR, "omp_for", tcc_sta
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)
@@ -2364,10 +2364,6 @@ dump_generic_node (pretty_printer *buffe
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;
@@ -2409,21 +2405,27 @@ dump_generic_node (pretty_printer *buffe
dump_generic_node (buffer, OMP_FOR_PRE_BODY (node),
spc, flags, false);
}
- spc -= 2;
- for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++)
+ if (OMP_FOR_INIT (node))
{
- spc += 2;
- newline_and_indent (buffer, spc);
- pp_string (buffer, "for (");
- dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INIT (node), i),
- spc, flags, false);
- pp_string (buffer, "; ");
- dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_COND (node), i),
- spc, flags, false);
- pp_string (buffer, "; ");
- dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INCR (node), i),
- spc, flags, false);
- pp_string (buffer, ")");
+ spc -= 2;
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++)
+ {
+ spc += 2;
+ newline_and_indent (buffer, spc);
+ pp_string (buffer, "for (");
+ dump_generic_node (buffer,
+ TREE_VEC_ELT (OMP_FOR_INIT (node), i),
+ spc, flags, false);
+ pp_string (buffer, "; ");
+ dump_generic_node (buffer,
+ TREE_VEC_ELT (OMP_FOR_COND (node), i),
+ spc, flags, false);
+ pp_string (buffer, "; ");
+ dump_generic_node (buffer,
+ TREE_VEC_ELT (OMP_FOR_INCR (node), i),
+ spc, flags, false);
+ pp_string (buffer, ")");
+ }
}
if (OMP_FOR_BODY (node))
{
@@ -2435,7 +2437,8 @@ dump_generic_node (pretty_printer *buffe
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '}');
}
- spc -= 2 * TREE_VEC_LENGTH (OMP_FOR_INIT (node)) - 2;
+ if (OMP_FOR_INIT (node))
+ spc -= 2 * TREE_VEC_LENGTH (OMP_FOR_INIT (node)) - 2;
if (OMP_FOR_PRE_BODY (node))
{
spc -= 4;
@@ -1030,112 +1030,6 @@ extern void pp_dir_change (cpp_reader *,
extern bool check_missing_format_attribute (tree, tree);
/* In c-omp.c */
-extern tree c_finish_omp_master (location_t, tree);
-extern tree c_finish_omp_critical (location_t, tree, tree);
-extern tree c_finish_omp_ordered (location_t, tree);
-extern void c_finish_omp_barrier (location_t);
-extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
- tree, tree, tree, tree, tree, bool, bool);
-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, enum tree_code, tree, tree, tree,
- tree, tree, tree);
-extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
-extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
-extern void c_omp_declare_simd_clauses_to_decls (tree, tree);
-extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
-
-/* Not in c-omp.c; provided by the front end. */
-extern bool c_omp_sharing_predetermined (tree);
-extern tree c_omp_remap_decl (tree, bool);
-extern void record_types_used_by_current_var_decl (tree);
-
-/* Return next tree in the chain for chain_next walking of tree nodes. */
-static inline tree
-c_tree_chain_next (tree t)
-{
- /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different
- kind of object, never a long chain of nodes. Prefer
- TYPE_NEXT_VARIANT for types. */
- if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON))
- return TYPE_NEXT_VARIANT (t);
- /* Otherwise, if there is TREE_CHAIN, return it. */
- if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
- return TREE_CHAIN (t);
- return NULL;
-}
-
-/* Mask used by tm_stmt_attr. */
-#define TM_STMT_ATTR_OUTER 2
-#define TM_STMT_ATTR_ATOMIC 4
-#define TM_STMT_ATTR_RELAXED 8
-
-extern int parse_tm_stmt_attr (tree, int);
-
-/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these
- are ordered specifically such that more restrictive attributes are
- at lower bit positions. This fact is known by the C++ tm attribute
- inheritance code such that least bit extraction (mask & -mask) results
- in the most restrictive attribute. */
-#define TM_ATTR_SAFE 1
-#define TM_ATTR_CALLABLE 2
-#define TM_ATTR_PURE 4
-#define TM_ATTR_IRREVOCABLE 8
-#define TM_ATTR_MAY_CANCEL_OUTER 16
-
-extern int tm_attr_to_mask (tree);
-extern tree tm_mask_to_attr (int);
-extern tree find_tm_attribute (tree);
-
-/* A suffix-identifier value doublet that represents user-defined literals
- for C++-0x. */
-enum overflow_type {
- OT_UNDERFLOW = -1,
- OT_NONE,
- OT_OVERFLOW
-};
-
-struct GTY(()) tree_userdef_literal {
- struct tree_base base;
- tree suffix_id;
- tree value;
- tree num_string;
- enum overflow_type overflow;
-};
-
-#define USERDEF_LITERAL_SUFFIX_ID(NODE) \
- (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id)
-
-#define USERDEF_LITERAL_VALUE(NODE) \
- (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
-
-#define USERDEF_LITERAL_OVERFLOW(NODE) \
- (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->overflow)
-
-#define USERDEF_LITERAL_NUM_STRING(NODE) \
- (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
-
-#define USERDEF_LITERAL_TYPE(NODE) \
- (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
-
-extern tree build_userdef_literal (tree suffix_id, tree value,
- enum overflow_type overflow,
- tree num_string);
-
-extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
-
-/* Possibe cases of scalar_to_vector conversion. */
-enum stv_conv {
- stv_error, /* Error occured. */
- stv_nothing, /* Nothing happened. */
- stv_firstarg, /* First argument must be expanded. */
- stv_secondarg /* Second argument must be expanded. */
-};
-
-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)
@@ -1261,4 +1155,123 @@ omp_clause_mask::operator == (omp_clause
# define OMP_CLAUSE_MASK_1 omp_clause_mask (1)
#endif
+enum c_omp_clause_split
+{
+ C_OMP_CLAUSE_SPLIT_TARGET = 0,
+ C_OMP_CLAUSE_SPLIT_TEAMS,
+ C_OMP_CLAUSE_SPLIT_DISTRIBUTE,
+ C_OMP_CLAUSE_SPLIT_PARALLEL,
+ C_OMP_CLAUSE_SPLIT_FOR,
+ C_OMP_CLAUSE_SPLIT_SIMD,
+ C_OMP_CLAUSE_SPLIT_COUNT,
+ C_OMP_CLAUSE_SPLIT_SECTIONS = C_OMP_CLAUSE_SPLIT_FOR
+};
+
+extern tree c_finish_omp_master (location_t, tree);
+extern tree c_finish_omp_critical (location_t, tree, tree);
+extern tree c_finish_omp_ordered (location_t, tree);
+extern void c_finish_omp_barrier (location_t);
+extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
+ tree, tree, tree, tree, tree, bool, bool);
+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, enum tree_code, tree, tree, tree,
+ tree, tree, tree);
+extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
+ tree, tree *);
+extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
+extern void c_omp_declare_simd_clauses_to_decls (tree, tree);
+extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
+
+/* Not in c-omp.c; provided by the front end. */
+extern bool c_omp_sharing_predetermined (tree);
+extern tree c_omp_remap_decl (tree, bool);
+extern void record_types_used_by_current_var_decl (tree);
+
+/* Return next tree in the chain for chain_next walking of tree nodes. */
+static inline tree
+c_tree_chain_next (tree t)
+{
+ /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different
+ kind of object, never a long chain of nodes. Prefer
+ TYPE_NEXT_VARIANT for types. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON))
+ return TYPE_NEXT_VARIANT (t);
+ /* Otherwise, if there is TREE_CHAIN, return it. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
+ return TREE_CHAIN (t);
+ return NULL;
+}
+
+/* Mask used by tm_stmt_attr. */
+#define TM_STMT_ATTR_OUTER 2
+#define TM_STMT_ATTR_ATOMIC 4
+#define TM_STMT_ATTR_RELAXED 8
+
+extern int parse_tm_stmt_attr (tree, int);
+
+/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these
+ are ordered specifically such that more restrictive attributes are
+ at lower bit positions. This fact is known by the C++ tm attribute
+ inheritance code such that least bit extraction (mask & -mask) results
+ in the most restrictive attribute. */
+#define TM_ATTR_SAFE 1
+#define TM_ATTR_CALLABLE 2
+#define TM_ATTR_PURE 4
+#define TM_ATTR_IRREVOCABLE 8
+#define TM_ATTR_MAY_CANCEL_OUTER 16
+
+extern int tm_attr_to_mask (tree);
+extern tree tm_mask_to_attr (int);
+extern tree find_tm_attribute (tree);
+
+/* A suffix-identifier value doublet that represents user-defined literals
+ for C++-0x. */
+enum overflow_type {
+ OT_UNDERFLOW = -1,
+ OT_NONE,
+ OT_OVERFLOW
+};
+
+struct GTY(()) tree_userdef_literal {
+ struct tree_base base;
+ tree suffix_id;
+ tree value;
+ tree num_string;
+ enum overflow_type overflow;
+};
+
+#define USERDEF_LITERAL_SUFFIX_ID(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id)
+
+#define USERDEF_LITERAL_VALUE(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
+
+#define USERDEF_LITERAL_OVERFLOW(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->overflow)
+
+#define USERDEF_LITERAL_NUM_STRING(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
+
+#define USERDEF_LITERAL_TYPE(NODE) \
+ (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
+
+extern tree build_userdef_literal (tree suffix_id, tree value,
+ enum overflow_type overflow,
+ tree num_string);
+
+extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
+
+/* Possibe cases of scalar_to_vector conversion. */
+enum stv_conv {
+ stv_error, /* Error occured. */
+ stv_nothing, /* Nothing happened. */
+ stv_firstarg, /* First argument must be expanded. */
+ stv_secondarg /* Second argument must be expanded. */
+};
+
+extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
+ tree op0, tree op1, bool);
+
#endif /* ! GCC_C_COMMON_H */
@@ -36,6 +36,9 @@ typedef enum pragma_kind {
PRAGMA_OMP_DECLARE_SIMD,
PRAGMA_OMP_DECLARE_TARGET,
PRAGMA_OMP_DISTRIBUTE,
+ PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR,
+ PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD,
+ PRAGMA_OMP_DISTRIBUTE_SIMD,
PRAGMA_OMP_END_DECLARE_TARGET,
PRAGMA_OMP_FLUSH,
PRAGMA_OMP_FOR,
@@ -52,6 +55,10 @@ typedef enum pragma_kind {
PRAGMA_OMP_SINGLE,
PRAGMA_OMP_TARGET,
PRAGMA_OMP_TARGET_DATA,
+ PRAGMA_OMP_TARGET_TEAMS,
+ PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE,
+ PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR,
+ PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD,
PRAGMA_OMP_TARGET_UPDATE,
PRAGMA_OMP_TASK,
PRAGMA_OMP_TASKGROUP,
@@ -59,6 +66,9 @@ typedef enum pragma_kind {
PRAGMA_OMP_TASKYIELD,
PRAGMA_OMP_THREADPRIVATE,
PRAGMA_OMP_TEAMS,
+ PRAGMA_OMP_TEAMS_DISTRIBUTE,
+ PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR,
+ PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD,
PRAGMA_GCC_PCH_PREPROCESS,
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.
#include "coretypes.h"
#include "tree.h"
#include "c-common.h"
+#include "c-pragma.h"
#include "gimple.h" /* For create_tmp_var_raw. */
#include "langhooks.h"
@@ -585,21 +586,55 @@ c_finish_omp_for (location_t locus, enum
}
}
-
-/* Divide CLAUSES into two lists: those that apply to a parallel
- construct, and those that apply to a work-sharing construct. Place
- the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In
- addition, add a nowait clause to the work-sharing list. LOC is the
- location of the OMP_PARALLEL*. */
+/* Right now we have 14 different combined constructs, this
+ function attempts to split or duplicate clauses for combined
+ constructs. CODE is the innermost construct in the combined construct,
+ and MASK allows to determine which constructs are combined together,
+ as every construct has at least one clause that no other construct
+ has (except for OMP_SECTIONS, but that can be only combined with parallel).
+ Combined constructs are:
+ #pragma omp parallel for
+ #pragma omp parallel sections
+ #pragma omp parallel for simd
+ #pragma omp for simd
+ #pragma omp distribute simd
+ #pragma omp distribute parallel for
+ #pragma omp distribute parallel for simd
+ #pragma omp teams distribute
+ #pragma omp teams distribute parallel for
+ #pragma omp teams distribute parallel for simd
+ #pragma omp target teams
+ #pragma omp target teams distribute
+ #pragma omp target teams distribute parallel for
+ #pragma omp target teams distribute parallel for simd */
void
-c_split_parallel_clauses (location_t loc, tree clauses,
- tree *par_clauses, tree *ws_clauses)
+c_omp_split_clauses (location_t loc, enum tree_code code,
+ omp_clause_mask mask, tree clauses, tree *cclauses)
{
- tree next;
+ tree next, c;
+ enum c_omp_clause_split s;
+ int i;
- *par_clauses = NULL;
- *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ cclauses[i] = NULL;
+ /* Add implicit nowait clause on
+ #pragma omp parallel {for,for simd,sections}. */
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ switch (code)
+ {
+ case OMP_FOR:
+ case OMP_SIMD:
+ cclauses[C_OMP_CLAUSE_SPLIT_FOR]
+ = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+ break;
+ case OMP_SECTIONS:
+ cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
+ = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+ break;
+ default:
+ break;
+ }
for (; clauses ; clauses = next)
{
@@ -607,36 +642,228 @@ c_split_parallel_clauses (location_t loc
switch (OMP_CLAUSE_CODE (clauses))
{
- case OMP_CLAUSE_PRIVATE:
- case OMP_CLAUSE_SHARED:
- case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_LASTPRIVATE:
- case OMP_CLAUSE_REDUCTION:
+ /* First the clauses that are unique to some constructs. */
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_MAP:
+ s = C_OMP_CLAUSE_SPLIT_TARGET;
+ break;
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ break;
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ break;
case OMP_CLAUSE_COPYIN:
- case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
- case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_PROC_BIND:
- OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
- *par_clauses = clauses;
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
break;
-
- case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_ORDERED:
- case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_NOWAIT:
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ break;
case OMP_CLAUSE_SAFELEN:
- case OMP_CLAUSE_ALIGNED:
case OMP_CLAUSE_LINEAR:
- OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
- *ws_clauses = clauses;
+ case OMP_CLAUSE_ALIGNED:
+ s = C_OMP_CLAUSE_SPLIT_SIMD;
+ break;
+ /* Duplicate this to all of distribute, for and simd. */
+ case OMP_CLAUSE_COLLAPSE:
+ if (code == OMP_SIMD)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_COLLAPSE_EXPR (c)
+ = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
+ }
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ {
+ if (mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_COLLAPSE_EXPR (c)
+ = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ }
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ }
+ else
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ break;
+ /* Private clause is supported on all constructs but target,
+ it is enough to put it on the innermost one. For
+ #pragma omp {for,sections} put it on parallel though,
+ as that's what we did for OpenMP 3.1. */
+ case OMP_CLAUSE_PRIVATE:
+ switch (code)
+ {
+ case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
+ case OMP_FOR: case OMP_SECTIONS:
+ case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
+ case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
+ case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
+ default: gcc_unreachable ();
+ }
+ break;
+ /* Firstprivate clause is supported on all constructs but
+ target and simd. Put it on the outermost of those and
+ duplicate on parallel. */
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ {
+ if (mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
+ | (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)))
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
+ if (mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ else
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ }
+ else
+ /* This must be
+ #pragma omp parallel{, for{, simd}, sections}. */
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ }
+ else if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ {
+ /* This must be #pragma omp {,target }teams distribute. */
+ gcc_assert (code == OMP_DISTRIBUTE);
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ }
+ else if (mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))
+ {
+ /* This must be #pragma omp distribute simd. */
+ gcc_assert (code == OMP_SIMD);
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ }
+ else
+ {
+ /* This must be #pragma omp for simd. */
+ gcc_assert (code == OMP_SIMD);
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ }
+ break;
+ /* Lastprivate is allowed on for, sections and simd. In
+ parallel {for{, simd},sections} we actually want to put it on
+ parallel rather than for or sections. */
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (code == OMP_FOR || code == OMP_SECTIONS)
+ {
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ break;
+ }
+ gcc_assert (code == OMP_SIMD);
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE))
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_LASTPRIVATE);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ OMP_CLAUSE_CHAIN (c) = cclauses[s];
+ cclauses[s] = c;
+ }
+ s = C_OMP_CLAUSE_SPLIT_SIMD;
+ break;
+ /* Shared and default clauses are allowed on private and teams. */
+ case OMP_CLAUSE_SHARED:
+ case OMP_CLAUSE_DEFAULT:
+ if (code == OMP_TEAMS)
+ {
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ break;
+ }
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_CODE (clauses));
+ if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ else
+ OMP_CLAUSE_DEFAULT_KIND (c)
+ = OMP_CLAUSE_DEFAULT_KIND (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
+
+ }
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ break;
+ /* Reduction is allowed on simd, for, parallel, sections and teams.
+ Duplicate it on all of them, but omit on for or sections if
+ parallel is present. */
+ case OMP_CLAUSE_REDUCTION:
+ if (code == OMP_SIMD)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_REDUCTION);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_REDUCTION_CODE (c)
+ = OMP_CLAUSE_REDUCTION_CODE (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
+ }
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE))
+ {
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_REDUCTION);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_REDUCTION_CODE (c)
+ = OMP_CLAUSE_REDUCTION_CODE (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ }
+ else if (mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ }
+ else if (code == OMP_SECTIONS)
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ break;
+ case OMP_CLAUSE_IF:
+ /* FIXME: This is currently being discussed. */
+ if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_TARGET;
break;
-
default:
gcc_unreachable ();
}
+ OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
+ cclauses[s] = clauses;
}
}
+
/* qsort callback to compare #pragma omp declare simd clauses. */
static int