summaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c101
1 files changed, 92 insertions, 9 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index ec88c65d846..ab324d349c1 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -60,6 +60,8 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "gomp-constants.h"
#include "c-family/c-indentation.h"
+#include "gimple-expr.h"
+#include "context.h"
/* Initialization routine for this file. */
@@ -11574,35 +11576,58 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
OpenMP 4.5:
schedule ( schedule-modifier : schedule-kind )
- schedule ( schedule-modifier : schedule-kind , expression )
+ schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
schedule-modifier:
- simd */
+ simd
+ monotonic
+ nonmonotonic */
static tree
c_parser_omp_clause_schedule (c_parser *parser, tree list)
{
tree c, t;
location_t loc = c_parser_peek_token (parser)->location;
+ int modifiers = 0, nmodifiers = 0;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
- if (c_parser_next_token_is (parser, CPP_NAME))
+ while (c_parser_next_token_is (parser, CPP_NAME))
{
tree kind = c_parser_peek_token (parser)->value;
const char *p = IDENTIFIER_POINTER (kind);
- if (strcmp ("simd", p) == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ if (strcmp ("simd", p) == 0)
+ OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
+ else if (strcmp ("monotonic", p) == 0)
+ modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
+ else if (strcmp ("nonmonotonic", p) == 0)
+ modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
+ else
+ break;
+ c_parser_consume_token (parser);
+ if (nmodifiers++ == 0
+ && c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
{
- OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+ break;
}
}
+ if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ == (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ {
+ error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
+ "specified");
+ modifiers = 0;
+ }
+
if (c_parser_next_token_is (parser, CPP_NAME))
{
tree kind = c_parser_peek_token (parser)->value;
@@ -11668,6 +11693,10 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<,%> or %<)%>");
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
+
check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -14139,8 +14168,15 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
{
stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv,
incrv, body, pre_body);
+
+ /* Check for iterators appearing in lb, b or incr expressions. */
+ if (stmt && !c_omp_check_loop_iv (stmt, declv, NULL))
+ stmt = NULL_TREE;
+
if (stmt)
{
+ add_stmt (stmt);
+
if (cclauses != NULL
&& cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
{
@@ -14823,6 +14859,7 @@ c_parser_omp_cancellation_point (c_parser *parser)
#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_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
@@ -14998,6 +15035,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser)
map_seen = 3;
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
+ case GOMP_MAP_ALWAYS_POINTER:
break;
default:
map_seen |= 1;
@@ -15131,6 +15169,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
map_seen = 3;
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
+ case GOMP_MAP_ALWAYS_POINTER:
break;
default:
map_seen |= 1;
@@ -15217,6 +15256,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
map_seen = 3;
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
+ case GOMP_MAP_ALWAYS_POINTER:
break;
default:
map_seen |= 1;
@@ -15342,6 +15382,32 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL_TREE)
return false;
+ if (ccode == OMP_TEAMS)
+ {
+ /* For combined target teams, ensure the num_teams and
+ thread_limit clause expressions are evaluated on the host,
+ before entering the target construct. */
+ tree c;
+ for (c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ c; c = OMP_CLAUSE_CHAIN (c))
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
+ && TREE_CODE (OMP_CLAUSE_OPERAND (c, 0)) != INTEGER_CST)
+ {
+ tree expr = OMP_CLAUSE_OPERAND (c, 0);
+ tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
+ expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
+ expr, NULL_TREE, NULL_TREE);
+ add_stmt (expr);
+ OMP_CLAUSE_OPERAND (c, 0) = expr;
+ tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (tc) = tmp;
+ OMP_CLAUSE_CHAIN (tc)
+ = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
+ cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
+ }
+ }
tree stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
@@ -15410,6 +15476,7 @@ check_clauses:
case GOMP_MAP_ALWAYS_TOFROM:
case GOMP_MAP_ALLOC:
case GOMP_MAP_FIRSTPRIVATE_POINTER:
+ case GOMP_MAP_ALWAYS_POINTER:
break;
default:
error_at (OMP_CLAUSE_LOCATION (*pc),
@@ -15679,6 +15746,7 @@ c_parser_omp_declare_target (c_parser *parser)
{
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE,
clauses);
+ clauses = c_finish_omp_clauses (clauses, true);
c_parser_skip_to_pragma_eol (parser);
}
else
@@ -15712,7 +15780,22 @@ c_parser_omp_declare_target (c_parser *parser)
continue;
}
if (!at1)
- DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ {
+ symtab_node *node = symtab_node::get (t);
+ DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ if (node != NULL)
+ {
+ node->offloadable = 1;
+#ifdef ENABLE_OFFLOADING
+ g->have_offload = true;
+ if (is_a <varpool_node *> (node))
+ {
+ vec_safe_push (offload_vars, t);
+ node->force_output = 1;
+ }
+#endif
+ }
+ }
}
}