@@ -41,6 +41,8 @@
#define GOMP_MAP_FLAG_SPECIAL_1 (1 << 3)
#define GOMP_MAP_FLAG_SPECIAL (GOMP_MAP_FLAG_SPECIAL_1 \
| GOMP_MAP_FLAG_SPECIAL_0)
+/* OpenMP always flag. */
+#define GOMP_MAP_FLAG_ALWAYS (1 << 6)
/* Flag to force a specific behavior (or else, trigger a run-time error). */
#define GOMP_MAP_FLAG_FORCE (1 << 7)
@@ -77,7 +79,21 @@ enum gomp_map_kind
/* ..., and copy from device. */
GOMP_MAP_FORCE_FROM = (GOMP_MAP_FLAG_FORCE | GOMP_MAP_FROM),
/* ..., and copy to and from device. */
- GOMP_MAP_FORCE_TOFROM = (GOMP_MAP_FLAG_FORCE | GOMP_MAP_TOFROM)
+ GOMP_MAP_FORCE_TOFROM = (GOMP_MAP_FLAG_FORCE | GOMP_MAP_TOFROM),
+ /* If not already present, allocate. And unconditionally copy to
+ device. */
+ GOMP_MAP_ALWAYS_TO = (GOMP_MAP_FLAG_ALWAYS | GOMP_MAP_TO),
+ /* If not already present, allocate. And unconditionally copy from
+ device. */
+ GOMP_MAP_ALWAYS_FROM = (GOMP_MAP_FLAG_ALWAYS | GOMP_MAP_FROM),
+ /* If not already present, allocate. And unconditionally copy to and from
+ device. */
+ GOMP_MAP_ALWAYS_TOFROM = (GOMP_MAP_FLAG_ALWAYS | GOMP_MAP_TOFROM),
+ /* OpenMP 4.1 alias for forced deallocation. */
+ GOMP_MAP_DELETE = GOMP_MAP_FORCE_DEALLOC,
+ /* Decrement usage count and deallocate if zero. */
+ GOMP_MAP_RELEASE = (GOMP_MAP_FLAG_ALWAYS
+ | GOMP_MAP_FORCE_DEALLOC)
};
#define GOMP_MAP_COPY_TO_P(X) \
@@ -12511,13 +12511,17 @@ lower_omp_target (gimple_stmt_iterator *
case GOMP_MAP_TOFROM:
case GOMP_MAP_POINTER:
case GOMP_MAP_TO_PSET:
+ case GOMP_MAP_FORCE_DEALLOC:
+ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ break;
case GOMP_MAP_FORCE_ALLOC:
case GOMP_MAP_FORCE_TO:
case GOMP_MAP_FORCE_FROM:
case GOMP_MAP_FORCE_TOFROM:
case GOMP_MAP_FORCE_PRESENT:
- case GOMP_MAP_FORCE_DEALLOC:
- break;
case GOMP_MAP_FORCE_DEVICEPTR:
gcc_assert (is_gimple_omp_oacc (stmt));
break;
@@ -560,26 +560,38 @@ dump_omp_clause (pretty_printer *pp, tre
pp_string (pp, "tofrom");
break;
case GOMP_MAP_FORCE_ALLOC:
- pp_string (pp, "always,alloc");
+ pp_string (pp, "force_alloc");
break;
case GOMP_MAP_FORCE_TO:
- pp_string (pp, "always,to");
+ pp_string (pp, "force_to");
break;
case GOMP_MAP_FORCE_FROM:
- pp_string (pp, "always,from");
+ pp_string (pp, "force_from");
break;
case GOMP_MAP_FORCE_TOFROM:
- pp_string (pp, "always,tofrom");
+ pp_string (pp, "force_tofrom");
break;
case GOMP_MAP_FORCE_PRESENT:
pp_string (pp, "force_present");
break;
case GOMP_MAP_FORCE_DEALLOC:
- pp_string (pp, "always,delete");
+ pp_string (pp, "delete");
break;
case GOMP_MAP_FORCE_DEVICEPTR:
pp_string (pp, "force_deviceptr");
break;
+ case GOMP_MAP_ALWAYS_TO:
+ pp_string (pp, "always,to");
+ break;
+ case GOMP_MAP_ALWAYS_FROM:
+ pp_string (pp, "always,from");
+ break;
+ case GOMP_MAP_ALWAYS_TOFROM:
+ pp_string (pp, "always,tofrom");
+ break;
+ case GOMP_MAP_RELEASE:
+ pp_string (pp, "release");
+ break;
default:
gcc_unreachable ();
}
@@ -11661,7 +11661,7 @@ c_parser_omp_clause_depend (c_parser *pa
OpenMP 4.1:
map-kind:
- alloc | to | from | tofrom | delete
+ alloc | to | from | tofrom | release | delete
map ( always [,] map-kind: variable-list ) */
@@ -11702,6 +11702,7 @@ c_parser_omp_clause_map (c_parser *parse
|| strcmp ("to", p) == 0
|| strcmp ("from", p) == 0
|| strcmp ("tofrom", p) == 0
+ || strcmp ("release", p) == 0
|| strcmp ("delete", p) == 0)
{
c_parser_consume_token (parser);
@@ -11718,13 +11719,15 @@ c_parser_omp_clause_map (c_parser *parse
if (strcmp ("alloc", p) == 0)
kind = GOMP_MAP_ALLOC;
else if (strcmp ("to", p) == 0)
- kind = GOMP_MAP_TO;
+ kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO;
else if (strcmp ("from", p) == 0)
- kind = GOMP_MAP_FROM;
+ kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM;
else if (strcmp ("tofrom", p) == 0)
- kind = GOMP_MAP_TOFROM;
+ kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM;
+ else if (strcmp ("release", p) == 0)
+ kind = GOMP_MAP_RELEASE;
else if (strcmp ("delete", p) == 0)
- kind = GOMP_MAP_FORCE_DEALLOC;
+ kind = GOMP_MAP_DELETE;
else
{
c_parser_error (parser, "invalid map kind");
@@ -11732,8 +11735,6 @@ c_parser_omp_clause_map (c_parser *parse
"expected %<)%>");
return list;
}
- if (always)
- kind = (enum gomp_map_kind) (kind | GOMP_MAP_FLAG_FORCE);
c_parser_consume_token (parser);
c_parser_consume_token (parser);
}
@@ -14237,11 +14238,40 @@ c_parser_omp_target_data (location_t loc
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
"#pragma omp target data");
- if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
+ int map_seen = 0;
+ for (tree *pc = &clauses; *pc;)
{
- error_at (loc,
- "%<#pragma omp target data%> must contain at least one "
- "%<map%> clause");
+ if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
+ {
+ case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_POINTER:
+ map_seen = 3;
+ break;
+ default:
+ map_seen |= 1;
+ error_at (OMP_CLAUSE_LOCATION (*pc),
+ "%<#pragma omp target data%> with map-type other "
+ "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
+ "on %<map%> clause");
+ *pc = OMP_CLAUSE_CHAIN (*pc);
+ continue;
+ }
+ pc = &OMP_CLAUSE_CHAIN (*pc);
+ }
+
+ if (map_seen != 3)
+ {
+ if (map_seen == 0)
+ error_at (loc,
+ "%<#pragma omp target data%> must contain at least "
+ "one %<map%> clause");
return NULL_TREE;
}
@@ -14348,10 +14378,12 @@ c_parser_omp_target_enter_data (location
for (tree *pc = &clauses; *pc;)
{
if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc) & ~GOMP_MAP_FLAG_FORCE)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
{
case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
case GOMP_MAP_ALLOC:
+ case GOMP_MAP_POINTER:
map_seen = 3;
break;
default:
@@ -14430,17 +14462,21 @@ c_parser_omp_target_exit_data (location_
for (tree *pc = &clauses; *pc;)
{
if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc) & ~GOMP_MAP_FLAG_FORCE)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
{
case GOMP_MAP_FROM:
- case GOMP_MAP_FORCE_DEALLOC & ~GOMP_MAP_FLAG_FORCE:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+ case GOMP_MAP_POINTER:
map_seen = 3;
break;
default:
map_seen |= 1;
error_at (OMP_CLAUSE_LOCATION (*pc),
"%<#pragma omp target exit data%> with map-type other "
- "than %<from%> or %<delete%> on %<map%> clause");
+ "than %<from%>, %<release> or %<delete%> on %<map%>"
+ " clause");
*pc = OMP_CLAUSE_CHAIN (*pc);
continue;
}
@@ -14480,6 +14516,7 @@ c_parser_omp_target (c_parser *parser, e
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
+ tree *pc = NULL, stmt, block;
if (context != pragma_stmt && context != pragma_compound)
{
@@ -14519,7 +14556,8 @@ c_parser_omp_target (c_parser *parser, e
OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
OMP_TARGET_BODY (stmt) = block;
add_stmt (stmt);
- return true;
+ pc = &OMP_TARGET_CLAUSES (stmt);
+ goto check_clauses;
}
else if (!flag_openmp) /* flag_openmp_simd */
{
@@ -14551,19 +14589,46 @@ c_parser_omp_target (c_parser *parser, e
}
}
- tree stmt = make_node (OMP_TARGET);
+ stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
OMP_TARGET_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
"#pragma omp target");
+ pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
- tree block = c_begin_compound_stmt (true);
+ block = c_begin_compound_stmt (true);
add_stmt (c_parser_omp_structured_block (parser));
OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
add_stmt (stmt);
+
+check_clauses:
+ while (*pc)
+ {
+ if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
+ {
+ case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_POINTER:
+ break;
+ default:
+ error_at (OMP_CLAUSE_LOCATION (*pc),
+ "%<#pragma omp target%> with map-type other "
+ "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
+ "on %<map%> clause");
+ *pc = OMP_CLAUSE_CHAIN (*pc);
+ continue;
+ }
+ pc = &OMP_CLAUSE_CHAIN (*pc);
+ }
return true;
}
@@ -29150,7 +29150,7 @@ cp_parser_omp_clause_depend (cp_parser *
OpenMP 4.1:
map-kind:
- alloc | to | from | tofrom | delete
+ alloc | to | from | tofrom | release | delete
map ( always [,] map-kind: variable-list ) */
@@ -29195,13 +29195,15 @@ cp_parser_omp_clause_map (cp_parser *par
if (strcmp ("alloc", p) == 0)
kind = GOMP_MAP_ALLOC;
else if (strcmp ("to", p) == 0)
- kind = GOMP_MAP_TO;
+ kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO;
else if (strcmp ("from", p) == 0)
- kind = GOMP_MAP_FROM;
+ kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM;
else if (strcmp ("tofrom", p) == 0)
- kind = GOMP_MAP_TOFROM;
+ kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM;
+ else if (strcmp ("release", p) == 0)
+ kind = GOMP_MAP_RELEASE;
else if (strcmp ("delete", p) == 0)
- kind = GOMP_MAP_FORCE_DEALLOC;
+ kind = GOMP_MAP_DELETE;
else
{
cp_parser_error (parser, "invalid map kind");
@@ -29210,8 +29212,6 @@ cp_parser_omp_clause_map (cp_parser *par
/*consume_paren=*/true);
return list;
}
- if (always)
- kind = (enum gomp_map_kind) (kind | GOMP_MAP_FLAG_FORCE);
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
}
@@ -31690,11 +31690,40 @@ cp_parser_omp_target_data (cp_parser *pa
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
"#pragma omp target data", pragma_tok);
- if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
+ int map_seen = 0;
+ for (tree *pc = &clauses; *pc;)
{
- error_at (pragma_tok->location,
- "%<#pragma omp target data%> must contain at least one "
- "%<map%> clause");
+ if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
+ {
+ case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_POINTER:
+ map_seen = 3;
+ break;
+ default:
+ map_seen |= 1;
+ error_at (OMP_CLAUSE_LOCATION (*pc),
+ "%<#pragma omp target data%> with map-type other "
+ "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
+ "on %<map%> clause");
+ *pc = OMP_CLAUSE_CHAIN (*pc);
+ continue;
+ }
+ pc = &OMP_CLAUSE_CHAIN (*pc);
+ }
+
+ if (map_seen != 3)
+ {
+ if (map_seen == 0)
+ error_at (pragma_tok->location,
+ "%<#pragma omp target data%> must contain at least "
+ "one %<map%> clause");
return NULL_TREE;
}
@@ -31759,10 +31788,12 @@ cp_parser_omp_target_enter_data (cp_pars
for (tree *pc = &clauses; *pc;)
{
if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc) & ~GOMP_MAP_FLAG_FORCE)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
{
case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
case GOMP_MAP_ALLOC:
+ case GOMP_MAP_POINTER:
map_seen = 3;
break;
default:
@@ -31842,17 +31873,21 @@ cp_parser_omp_target_exit_data (cp_parse
for (tree *pc = &clauses; *pc;)
{
if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc) & ~GOMP_MAP_FLAG_FORCE)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
{
case GOMP_MAP_FROM:
- case GOMP_MAP_FORCE_DEALLOC & ~GOMP_MAP_FLAG_FORCE:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+ case GOMP_MAP_POINTER:
map_seen = 3;
break;
default:
map_seen |= 1;
error_at (OMP_CLAUSE_LOCATION (*pc),
"%<#pragma omp target exit data%> with map-type other "
- "than %<from%> or %<delete%> on %<map%> clause");
+ "than %<from%>, %<release%> or %<delete%> on %<map%>"
+ " clause");
*pc = OMP_CLAUSE_CHAIN (*pc);
continue;
}
@@ -31934,6 +31969,8 @@ static bool
cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
enum pragma_context context)
{
+ tree *pc = NULL, stmt;
+
if (context != pragma_stmt && context != pragma_compound)
{
cp_parser_error (parser, "expected declaration specifiers");
@@ -31975,7 +32012,8 @@ cp_parser_omp_target (cp_parser *parser,
OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
OMP_TARGET_BODY (stmt) = body;
add_stmt (stmt);
- return true;
+ pc = &OMP_TARGET_CLAUSES (stmt);
+ goto check_clauses;
}
else if (!flag_openmp) /* flag_openmp_simd */
{
@@ -32007,17 +32045,44 @@ cp_parser_omp_target (cp_parser *parser,
}
}
- tree stmt = make_node (OMP_TARGET);
+ stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
OMP_TARGET_CLAUSES (stmt)
= cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
"#pragma omp target", pragma_tok);
+ pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level (true);
OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser);
SET_EXPR_LOCATION (stmt, pragma_tok->location);
add_stmt (stmt);
+
+check_clauses:
+ while (*pc)
+ {
+ if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
+ switch (OMP_CLAUSE_MAP_KIND (*pc))
+ {
+ case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_POINTER:
+ break;
+ default:
+ error_at (OMP_CLAUSE_LOCATION (*pc),
+ "%<#pragma omp target%> with map-type other "
+ "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
+ "on %<map%> clause");
+ *pc = OMP_CLAUSE_CHAIN (*pc);
+ continue;
+ }
+ pc = &OMP_CLAUSE_CHAIN (*pc);
+ }
return true;
}