This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp4] Bring C FE again to feature parity with C++ FE OpenMP 4.0 handling
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, "Joseph S. Myers" <joseph at codesourcery dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sat, 6 Jul 2013 20:46:59 +0200
- Subject: [gomp4] Bring C FE again to feature parity with C++ FE OpenMP 4.0 handling
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
This patch syncs another almost two months of C++ FE only changes to
the C FE. Regtested on x86_64-linux, committed to gomp-4_0-branch.
2013-07-06 Jakub Jelinek <jakub@redhat.com>
gcc/c/
* c-lang.h (current_omp_declare_target_attribute): New extern
decl.
* Make-lang.in (c/c-parser.o): Depend on c/c-lang.h.
* c-parser.c: Include c-lang.h.
(c_parser_pragma): Handle PRAGMA_OMP_TARGET and
PRAGMA_OMP_END_DECLARE_TARGET.
(c_parser_omp_clause_name): Handle thread_limit clause.
(c_parser_omp_variable_list): Parse array sections for
OMP_CLAUSE_{DEPEND,MAP,TO,FROM} clauses.
(c_parser_omp_clause_reduction): Remove declare_simd argument.
Pass false instead of declare_simd to c_parser_omp_variable_list.
(c_parser_omp_clause_cancelkind): Remove diagnostics.
(c_parser_omp_clause_thread_limit): New function.
(c_parser_omp_all_clauses): Add finish_p argument. Don't call
c_finish_omp_clauses if it is false. Require that
OMP_CLAUSE_{PARALLEL,FOR,SECTIONS,TASKGROUP} must be first in
the list of clauses. Adjust c_parser_omp_clause_reduction
caller.
(c_parser_omp_for_loop): Change last argument to cclauses,
and adjust uses to grab parallel clauses from the array of all
the split clauses.
(omp_split_clauses): New function.
(c_parser_omp_simd): Add p_name, mask and cclauses arguments.
Allow the function to be called also when parsing combined constructs.
(c_parser_omp_sections): Likewise.
(c_parser_omp_for): Add p_name, mask and cclauses arguments.
Allow the function to be called also when parsing combined constructs,
and call cp_parser_omp_simd when parsing for simd.
(c_parser_omp_parallel): Likewise.
(c_parser_omp_single, c_parser_omp_task, c_parser_omp_cancel,
c_parser_omp_cancellation_point, c_parser_omp_declare_simd): Adjust
c_parser_omp_all_clauses callers.
(OMP_TEAMS_CLAUSE_MASK, OMP_TARGET_CLAUSE_MASK,
OMP_TARGET_DATA_CLAUSE_MASK, OMP_TARGET_UPDATE_CLAUSE_MASK,
OMP_DISTRIBUTE_CLAUSE_MASK): Define.
(c_parser_omp_teams, c_parser_omp_target, c_parser_omp_target_data,
c_parser_omp_target_update, c_parser_omp_distribute): New
functions.
(c_parser_omp_construct): Handle PRAGMA_OMP_DISTRIBUTE and
PRAGMA_OMP_TEAMS. Adjust callers of c_parser_omp_simd,
c_parser_omp_sections, c_parser_omp_for and c_parser_omp_parallel.
(OMP_DECLARE_SIMD_CLAUSE_MASK): Remove OMP_CLAUSE_REDUCTION.
(c_parser_omp_declare_target, c_parser_omp_end_declare_target): New
functions.
(c_parser_omp_declare): For target keyword call
c_parser_omp_declare_target. Adjust expected keyword diagnostics.
* c-decl.c (current_omp_declare_target_attribute): New variable.
(c_decl_attributes): New function.
(start_decl, start_function): Use it instead of decl_attributes.
* c-typeck.c (handle_omp_array_sections_1, handle_omp_array_sections):
New functions.
(c_finish_omp_clauses): Handle array sections on
OMP_CLAUSE_{MAP,TO,FROM,DEPEND}. If not array sections, mark the
decl addressable. Complain if OMP_CLAUSE_{MAP,TO,FROM}
decls or array sections don't have complete type. Handle
OMP_CLAUSE_THREAD_LIMIT.
gcc/cp/
* parser.c (cp_parser_omp_end_declare_target): Diagnose if
#pragma omp end isn't followed by declare target.
(cp_parser_omp_declare): Adjust expected keyword diagnostics.
gcc/testsuite/
* c-c++-common/gomp/depend-1.c: Enable for C as well.
* c-c++-common/gomp/depend-2.c: Likewise.
* c-c++-common/gomp/map-1.c: Likewise.
gcc/c-family/
* c-pragma.h (enum pragma_kind): Remove PRAGMA_OMP_DECLARE_SIMD,
PRAGMA_OMP_DECLARE_TARGET, PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR,
PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD, PRAGMA_OMP_DISTRIBUTE_SIMD,
PRAGMA_OMP_FOR_SIMD, PRAGMA_OMP_PARALLEL_FOR,
PRAGMA_OMP_PARALLEL_FOR_SIMD, PRAGMA_OMP_PARALLEL_SECTIONS,
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_TEAMS_DISTRIBUTE,
PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR and
PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD.
libgomp/
* testsuite/libgomp.c/for-3.c: New test.
* testsuite/libgomp.c/simd-1.c: New test.
* testsuite/libgomp.c/simd-2.c: New test.
* testsuite/libgomp.c/simd-3.c: New test.
--- gcc/c/c-lang.h.jj 2013-03-20 10:04:58.000000000 +0100
+++ gcc/c/c-lang.h 2013-07-06 17:29:09.733747004 +0200
@@ -55,5 +55,8 @@ struct GTY(()) language_function {
int warn_about_return_type;
};
+/* If non-zero, implicit "omp declare target" attribute is added into the
+ attribute lists. */
+extern GTY(()) int current_omp_declare_target_attribute;
#endif /* ! GCC_C_LANG_H */
--- gcc/c/Make-lang.in.jj 2013-06-26 12:13:51.000000000 +0200
+++ gcc/c/Make-lang.in 2013-07-06 17:31:02.763880113 +0200
@@ -181,8 +181,8 @@ c/c-objc-common.o : c/c-objc-common.c c/
$(TREE_PRETTY_PRINT_H)
c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
- $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
+ $(TM_H) $(TREE_H) c/c-lang.h $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) \
+ $(CPPLIB_H) $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
gt-c-c-parser.h langhooks.h \
$(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
c-family/c-objc.h
--- gcc/c/c-parser.c.jj 2013-07-03 22:15:07.000000000 +0200
+++ gcc/c/c-parser.c 2013-07-06 19:59:14.729863508 +0200
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.
#include "timevar.h"
#include "c-family/c-pragma.h"
#include "c-tree.h"
+#include "c-lang.h"
#include "flags.h"
#include "ggc.h"
#include "c-family/c-common.h"
@@ -1192,6 +1193,8 @@ static void c_parser_omp_cancellation_po
enum pragma_context { pragma_external, pragma_struct, pragma_param,
pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context);
+static bool c_parser_omp_target (c_parser *, enum pragma_context);
+static void c_parser_omp_end_declare_target (c_parser *);
static void c_parser_omp_declare (c_parser *, enum pragma_context);
/* These Objective-C parser functions are only ever called when
@@ -8803,6 +8806,13 @@ c_parser_pragma (c_parser *parser, enum
c_parser_omp_threadprivate (parser);
return false;
+ case PRAGMA_OMP_TARGET:
+ return c_parser_omp_target (parser, context);
+
+ case PRAGMA_OMP_END_DECLARE_TARGET:
+ c_parser_omp_end_declare_target (parser);
+ return false;
+
case PRAGMA_OMP_SECTION:
error_at (c_parser_peek_token (parser)->location,
"%<#pragma omp section%> may only be used in "
@@ -8996,6 +9006,8 @@ c_parser_omp_clause_name (c_parser *pars
case 't':
if (!strcmp ("taskgroup", p))
result = PRAGMA_OMP_CLAUSE_TASKGROUP;
+ else if (!strcmp ("thread_limit", p))
+ result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
else if (!strcmp ("to", p))
result = PRAGMA_OMP_CLAUSE_TO;
break;
@@ -9064,22 +9076,70 @@ c_parser_omp_variable_list (c_parser *pa
t = lookup_name (c_parser_peek_token (parser)->value);
if (t == NULL_TREE)
- undeclared_variable (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
- else if (t == error_mark_node)
+ {
+ undeclared_variable (c_parser_peek_token (parser)->location,
+ c_parser_peek_token (parser)->value);
+ t = error_mark_node;
+ }
+
+ c_parser_consume_token (parser);
+
+ if (t == error_mark_node)
;
else if (kind != 0)
{
- tree u = build_omp_clause (clause_loc, kind);
- OMP_CLAUSE_DECL (u) = t;
- OMP_CLAUSE_CHAIN (u) = list;
- list = u;
+ switch (kind)
+ {
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_DEPEND:
+ while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+ {
+ tree low_bound = NULL_TREE, length = NULL_TREE;
+
+ c_parser_consume_token (parser);
+ if (!c_parser_next_token_is (parser, CPP_COLON))
+ low_bound = c_parser_expression (parser).value;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ length = integer_one_node;
+ else
+ {
+ /* Look for `:'. */
+ if (!c_parser_require (parser, CPP_COLON,
+ "expected %<:%>"))
+ {
+ t = error_mark_node;
+ break;
+ }
+ if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ length = c_parser_expression (parser).value;
+ }
+ /* Look for the closing `]'. */
+ if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>"))
+ {
+ t = error_mark_node;
+ break;
+ }
+ t = tree_cons (low_bound, length, t);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (t != error_mark_node)
+ {
+ tree u = build_omp_clause (clause_loc, kind);
+ OMP_CLAUSE_DECL (u) = t;
+ OMP_CLAUSE_CHAIN (u) = list;
+ list = u;
+ }
}
else
list = tree_cons (t, NULL_TREE, list);
- c_parser_consume_token (parser);
-
if (c_parser_next_token_is_not (parser, CPP_COMMA))
break;
@@ -9401,7 +9461,7 @@ c_parser_omp_clause_private (c_parser *p
One of: + * - & ^ | && || max min */
static tree
-c_parser_omp_clause_reduction (c_parser *parser, tree list, bool declare_simd)
+c_parser_omp_clause_reduction (c_parser *parser, tree list)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -9463,8 +9523,7 @@ c_parser_omp_clause_reduction (c_parser
tree nl, c;
nl = c_parser_omp_variable_list (parser, clause_loc,
- OMP_CLAUSE_REDUCTION, list,
- declare_simd);
+ OMP_CLAUSE_REDUCTION, list, false);
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_REDUCTION_CODE (c) = code;
@@ -9622,24 +9681,7 @@ static tree
c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
enum omp_clause_code code, tree list)
{
- tree c;
- location_t loc = c_parser_peek_token (parser)->location;
-
- 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 (loc, "only one of %<parallel%>, %<for%>, %<sections%> "
- "and %<taskgroup%> clauses can be specified");
- break;
- default:
- break;
- }
-
- c = build_omp_clause (loc, code);
+ tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -9690,6 +9732,51 @@ c_parser_omp_clause_num_teams (c_parser
}
/* OpenMP 4.0:
+ thread_limit ( expression ) */
+
+static tree
+c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
+{
+ location_t num_teams_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ tree c, t = c_parser_expression (parser).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+
+ /* Attempt to statically determine when the number isn't positive. */
+ c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
+ build_int_cst (TREE_TYPE (t), 0));
+ if (CAN_HAVE_LOCATION_P (c))
+ SET_EXPR_LOCATION (c, expr_loc);
+ if (c == boolean_true_node)
+ {
+ warning_at (expr_loc, 0, "%<thread_limit%> value must be positive");
+ t = integer_one_node;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
+ "thread_limit");
+
+ c = build_omp_clause (num_teams_loc, OMP_CLAUSE_THREAD_LIMIT);
+ OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
+/* OpenMP 4.0:
aligned ( variable-list )
aligned ( variable-list : constant-expression ) */
@@ -10106,7 +10193,8 @@ c_parser_omp_clause_uniform (c_parser *p
static tree
c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
- const char *where, bool declare_simd)
+ const char *where, bool finish_p = true,
+ bool declare_simd = false)
{
tree clauses = NULL;
bool first = true;
@@ -10121,7 +10209,6 @@ c_parser_omp_all_clauses (c_parser *pars
if (!first && c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
- first = false;
here = c_parser_peek_token (parser)->location;
c_kind = c_parser_omp_clause_name (parser);
@@ -10180,8 +10267,7 @@ c_parser_omp_all_clauses (c_parser *pars
c_name = "private";
break;
case PRAGMA_OMP_CLAUSE_REDUCTION:
- clauses = c_parser_omp_clause_reduction (parser, clauses,
- declare_simd);
+ clauses = c_parser_omp_clause_reduction (parser, clauses);
c_name = "reduction";
break;
case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -10211,24 +10297,37 @@ c_parser_omp_all_clauses (c_parser *pars
= c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
clauses);
c_name = "parallel";
+ if (!first)
+ {
+ clause_not_first:
+ error_at (here, "%qs must be the first clause of %qs",
+ c_name, where);
+ clauses = prev;
+ }
break;
case PRAGMA_OMP_CLAUSE_FOR:
clauses
= c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
clauses);
c_name = "for";
+ if (!first)
+ goto clause_not_first;
break;
case PRAGMA_OMP_CLAUSE_SECTIONS:
clauses
= c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
clauses);
c_name = "sections";
+ if (!first)
+ goto clause_not_first;
break;
case PRAGMA_OMP_CLAUSE_TASKGROUP:
clauses
= c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
clauses);
c_name = "taskgroup";
+ if (!first)
+ goto clause_not_first;
break;
case PRAGMA_OMP_CLAUSE_TO:
clauses = c_parser_omp_clause_to (parser, clauses);
@@ -10246,6 +10345,10 @@ c_parser_omp_all_clauses (c_parser *pars
clauses = c_parser_omp_clause_num_teams (parser, clauses);
c_name = "num_teams";
break;
+ case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
+ clauses = c_parser_omp_clause_thread_limit (parser, clauses);
+ c_name = "thread_limit";
+ break;
case PRAGMA_OMP_CLAUSE_ALIGNED:
clauses = c_parser_omp_clause_aligned (parser, clauses,
declare_simd);
@@ -10288,6 +10391,8 @@ c_parser_omp_all_clauses (c_parser *pars
goto saw_error;
}
+ first = false;
+
if (((mask >> c_kind) & 1) == 0 && !parser->error)
{
/* Remove the invalid clause(s) from the list to avoid
@@ -10300,10 +10405,10 @@ c_parser_omp_all_clauses (c_parser *pars
saw_error:
c_parser_skip_to_pragma_eol (parser);
- if (declare_simd)
- return clauses;
+ if (finish_p)
+ return c_finish_omp_clauses (clauses);
- return c_finish_omp_clauses (clauses);
+ return clauses;
}
/* OpenMP 2.5:
@@ -10785,7 +10890,7 @@ c_parser_omp_flush (c_parser *parser)
static tree
c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
- tree clauses, tree *par_clauses)
+ tree clauses, tree *cclauses)
{
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
tree declv, condv, incrv, initv, ret = NULL;
@@ -11017,10 +11122,11 @@ c_parser_omp_for_loop (location_t loc, c
incrv, body, NULL);
if (stmt)
{
- if (par_clauses != NULL)
+ if (cclauses != NULL
+ && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
{
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_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
c = &OMP_CLAUSE_CHAIN (*c);
@@ -11069,6 +11175,20 @@ pop_scopes:
return ret;
}
+/* Helper function for OpenMP parsing, split clauses and call
+ finish_omp_clauses on each of the set of clauses afterwards. */
+
+static void
+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] = c_finish_omp_clauses (cclauses[i]);
+}
+
/* OpenMP 4.0:
#pragma omp simd simd-clause[optseq] new-line
for-loop
@@ -11086,15 +11206,24 @@ pop_scopes:
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
-c_parser_omp_simd (location_t loc, c_parser *parser)
+c_parser_omp_simd (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree block, clauses, ret;
- clauses = c_parser_omp_all_clauses (parser, OMP_SIMD_CLAUSE_MASK,
- "#pragma omp simd", false);
+ strcat (p_name, " simd");
+ mask |= OMP_SIMD_CLAUSE_MASK;
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ }
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -11123,12 +11252,15 @@ c_parser_omp_simd (location_t loc, c_par
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_for (location_t loc, c_parser *parser)
+c_parser_omp_for (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree block, clauses, ret;
- enum tree_code code = OMP_FOR;
- omp_clause_mask mask = OMP_FOR_CLAUSE_MASK;
- const char *p_name = "#pragma omp for";
+
+ strcat (p_name, " for");
+ mask |= OMP_FOR_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
if (c_parser_next_token_is (parser, CPP_NAME))
{
@@ -11136,17 +11268,35 @@ c_parser_omp_for (location_t loc, c_pars
if (strcmp (p, "simd") == 0)
{
- c_parser_consume_token (parser);
- /* code = OMP_FOR_SIMD; */
- mask |= OMP_SIMD_CLAUSE_MASK;
- p_name = "#pragma omp for simd";
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL_TREE)
+ return ret;
+ ret = make_node (OMP_FOR);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = block;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
}
}
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, false);
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ }
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, code, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -11270,12 +11420,22 @@ c_parser_omp_sections_scope (location_t
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_sections (location_t loc, c_parser *parser)
+c_parser_omp_sections (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree block, clauses, ret;
- clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
- "#pragma omp sections", false);
+ strcat (p_name, " sections");
+ mask |= OMP_SECTIONS_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
+ }
block = c_begin_compound_stmt (true);
ret = c_parser_omp_sections_scope (loc, parser);
@@ -11307,93 +11467,60 @@ c_parser_omp_sections (location_t loc, c
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
-c_parser_omp_parallel (location_t loc, c_parser *parser)
+c_parser_omp_parallel (location_t loc, c_parser *parser,
+ 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 cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+ tree stmt, clauses, block;
+
+ strcat (p_name, " parallel");
+ mask |= OMP_PARALLEL_CLAUSE_MASK;
if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
c_parser_consume_token (parser);
- 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 (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "simd") == 0)
- {
- c_parser_consume_token (parser);
- p_kind = PRAGMA_OMP_PARALLEL_FOR_SIMD;
- p_name = "#pragma omp parallel for simd";
- mask |= OMP_SIMD_CLAUSE_MASK;
- }
- }
+ block = c_begin_omp_parallel ();
+ c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ stmt
+ = c_finish_omp_parallel (loc, 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);
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
}
else if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "sections") == 0)
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
c_parser_consume_token (parser);
- 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 = c_begin_omp_parallel ();
+ c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
+ stmt = c_finish_omp_parallel (loc,
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
}
}
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, false);
-
- switch (p_kind)
- {
- case PRAGMA_OMP_PARALLEL:
- block = c_begin_omp_parallel ();
- c_parser_statement (parser);
- stmt = c_finish_omp_parallel (loc, clauses, block);
- break;
-
- case PRAGMA_OMP_PARALLEL_FOR:
- block = c_begin_omp_parallel ();
- 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;
- break;
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- case PRAGMA_OMP_PARALLEL_FOR_SIMD:
- block = c_begin_omp_parallel ();
- 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;
- break;
-
- case PRAGMA_OMP_PARALLEL_SECTIONS:
- block = c_begin_omp_parallel ();
- 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;
- stmt = c_finish_omp_parallel (loc, par_clause, block);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- break;
-
- default:
- gcc_unreachable ();
- }
+ block = c_begin_omp_parallel ();
+ c_parser_statement (parser);
+ stmt = c_finish_omp_parallel (loc, clauses, block);
return stmt;
}
@@ -11420,7 +11547,7 @@ c_parser_omp_single (location_t loc, c_p
OMP_SINGLE_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
- "#pragma omp single", false);
+ "#pragma omp single");
OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
return add_stmt (stmt);
@@ -11449,7 +11576,7 @@ c_parser_omp_task (location_t loc, c_par
tree clauses, block;
clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
- "#pragma omp task", false);
+ "#pragma omp task");
block = c_begin_omp_task ();
c_parser_statement (parser);
@@ -11519,7 +11646,7 @@ c_parser_omp_cancel (c_parser *parser)
c_parser_consume_pragma (parser);
tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
- "#pragma omp cancel", false);
+ "#pragma omp cancel");
c_finish_omp_cancel (loc, clauses);
}
@@ -11562,12 +11689,280 @@ c_parser_omp_cancellation_point (c_parse
clauses
= c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
- "#pragma omp cancellation point", false);
+ "#pragma omp cancellation point");
c_finish_omp_cancellation_point (loc, clauses);
}
/* 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
+c_parser_omp_distribute (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, block, ret;
+
+ strcat (p_name, " distribute");
+ mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ bool simd = false;
+ bool parallel = false;
+
+ if (strcmp (p, "simd") == 0)
+ simd = true;
+ else
+ parallel = strcmp (p, "parallel") == 0;
+ if (parallel || simd)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (true);
+ if (simd)
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ else
+ ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL)
+ return ret;
+ ret = make_node (OMP_DISTRIBUTE);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = block;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
+ }
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ }
+
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL);
+ block = c_end_compound_stmt (loc, block, true);
+ add_stmt (block);
+
+ return ret;
+}
+
+/* OpenMP 4.0:
+ # pragma omp teams teams-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TEAMS_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_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
+
+static tree
+c_parser_omp_teams (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, block, ret;
+
+ strcat (p_name, " teams");
+ mask |= OMP_TEAMS_CLAUSE_MASK;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "distribute") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ 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) = block;
+ return add_stmt (ret);
+ }
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ 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) = clauses;
+ OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+ return add_stmt (stmt);
+}
+
+/* OpenMP 4.0:
+ # pragma omp target data target-data-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TARGET_DATA_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static tree
+c_parser_omp_target_data (location_t loc, c_parser *parser)
+{
+ tree stmt = make_node (OMP_TARGET_DATA);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_TARGET_DATA_CLAUSES (stmt)
+ = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
+ "#pragma omp target data");
+ OMP_TARGET_DATA_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+ SET_EXPR_LOCATION (stmt, loc);
+ return add_stmt (stmt);
+}
+
+/* OpenMP 4.0:
+ # pragma omp target update target-update-clause[optseq] new-line */
+
+#define OMP_TARGET_UPDATE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static bool
+c_parser_omp_target_update (location_t loc, c_parser *parser,
+ enum pragma_context context)
+{
+ if (context == pragma_stmt)
+ {
+ error_at (loc,
+ "%<#pragma omp target update%> may only be "
+ "used in compound statements");
+ c_parser_skip_to_pragma_eol (parser);
+ return false;
+ }
+
+ tree clauses
+ = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
+ "#pragma omp target update");
+ if (find_omp_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
+ && find_omp_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
+ {
+ error_at (loc,
+ "%<#pragma omp target update must contain at least one "
+ "%<from%> or %<to%> clauses");
+ return false;
+ }
+
+ tree stmt = make_node (OMP_TARGET_UPDATE);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
+ SET_EXPR_LOCATION (stmt, loc);
+ add_stmt (stmt);
+ return false;
+}
+
+/* OpenMP 4.0:
+ # pragma omp target target-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TARGET_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static bool
+c_parser_omp_target (c_parser *parser, enum pragma_context context)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+
+ if (context != pragma_stmt && context != pragma_compound)
+ {
+ c_parser_error (parser, "expected declaration specifiers");
+ c_parser_skip_to_pragma_eol (parser);
+ return false;
+ }
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ if (strcmp (p, "data") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_target_data (loc, parser);
+ return true;
+ }
+ else if (strcmp (p, "update") == 0)
+ {
+ c_parser_consume_token (parser);
+ return c_parser_omp_target_update (loc, parser, context);
+ }
+ else if (strcmp (p, "teams") == 0)
+ {
+ tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+ char p_name[sizeof ("#pragma omp target teams distribute "
+ "parallel for simd")];
+
+ c_parser_consume_token (parser);
+ strcpy (p_name, "#pragma omp target");
+ tree block = c_begin_compound_stmt (true);
+ tree ret = c_parser_omp_teams (loc, parser, p_name,
+ OMP_TARGET_CLAUSE_MASK, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ 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) = block;
+ add_stmt (stmt);
+ return true;
+ }
+ }
+
+ tree 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");
+ OMP_TARGET_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+ SET_EXPR_LOCATION (stmt, loc);
+ add_stmt (stmt);
+ return true;
+}
+
+/* OpenMP 4.0:
# pragma omp declare simd declare-simd-clauses[optseq] new-line */
#define OMP_DECLARE_SIMD_CLAUSE_MASK \
@@ -11575,7 +11970,6 @@ c_parser_omp_cancellation_point (c_parse
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
@@ -11584,7 +11978,7 @@ c_parser_omp_declare_simd (c_parser *par
{
vec<tree> clauses = vNULL;
tree cl = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
- "#pragma omp declare simd", true);
+ "#pragma omp declare simd", false, true);
clauses.safe_push (cl);
while (c_parser_next_token_is (parser, CPP_PRAGMA))
@@ -11606,7 +12000,7 @@ c_parser_omp_declare_simd (c_parser *par
c_parser_consume_pragma (parser);
c_parser_consume_token (parser);
cl = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
- "#pragma omp declare simd", true);
+ "#pragma omp declare simd", false, true);
clauses.safe_push (cl);
}
@@ -11668,10 +12062,58 @@ c_parser_omp_declare_simd (c_parser *par
clauses.release ();
}
+/* OpenMP 4.0:
+ # pragma omp declare target new-line
+ declarations and definitions
+ # pragma omp end declare target new-line */
+
+static void
+c_parser_omp_declare_target (c_parser *parser)
+{
+ c_parser_skip_to_pragma_eol (parser);
+ current_omp_declare_target_attribute++;
+}
+
+static void
+c_parser_omp_end_declare_target (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "declare") == 0)
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "target") == 0)
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_error (parser, "expected %<target%>");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<declare%>");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ c_parser_skip_to_pragma_eol (parser);
+ if (!current_omp_declare_target_attribute)
+ error_at (loc, "%<#pragma omp end declare target%> without corresponding "
+ "%<#pragma omp declare target%>");
+ else
+ current_omp_declare_target_attribute--;
+}
+
/* OpenMP 4.0
#pragma omp declare simd declare-simd-clauses[optseq] new-line
#pragma omp declare reduction (reduction-id : typename-list : expression) \
- identity-clause[opt] new-line */
+ identity-clause[opt] new-line
+ #pragma omp declare target new-line */
static void
c_parser_omp_declare (c_parser *parser, enum pragma_context context)
@@ -11692,9 +12134,16 @@ c_parser_omp_declare (c_parser *parser,
c_parser_omp_declare_reduction (parser);
return;
} */
+ if (strcmp (p, "target") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_declare_target (parser);
+ return;
+ }
}
- c_parser_error (parser, "expected %<simd%> or %<reduction%>");
+ c_parser_error (parser, "expected %<simd%> or %<reduction%> "
+ "or %<target%>");
c_parser_skip_to_pragma_eol (parser);
}
@@ -11706,6 +12155,8 @@ c_parser_omp_construct (c_parser *parser
enum pragma_kind p_kind;
location_t loc;
tree stmt;
+ char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
+ omp_clause_mask mask (0);
loc = c_parser_peek_token (parser)->location;
p_kind = c_parser_peek_token (parser)->pragma_kind;
@@ -11719,8 +12170,13 @@ c_parser_omp_construct (c_parser *parser
case PRAGMA_OMP_CRITICAL:
stmt = c_parser_omp_critical (loc, parser);
break;
+ case PRAGMA_OMP_DISTRIBUTE:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL);
+ break;
case PRAGMA_OMP_FOR:
- stmt = c_parser_omp_for (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_MASTER:
stmt = c_parser_omp_master (loc, parser);
@@ -11729,13 +12185,16 @@ c_parser_omp_construct (c_parser *parser
stmt = c_parser_omp_ordered (loc, parser);
break;
case PRAGMA_OMP_PARALLEL:
- stmt = c_parser_omp_parallel (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_SECTIONS:
- stmt = c_parser_omp_sections (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_SIMD:
- stmt = c_parser_omp_simd (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_SINGLE:
stmt = c_parser_omp_single (loc, parser);
@@ -11746,6 +12205,10 @@ c_parser_omp_construct (c_parser *parser
case PRAGMA_OMP_TASKGROUP:
c_parser_omp_taskgroup (parser);
return;
+ case PRAGMA_OMP_TEAMS:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL);
+ break;
default:
gcc_unreachable ();
}
--- gcc/c/c-decl.c.jj 2013-06-26 12:13:51.000000000 +0200
+++ gcc/c/c-decl.c 2013-07-06 18:34:37.499264094 +0200
@@ -147,6 +147,9 @@ static bool undef_nested_function;
enum machine_mode c_default_pointer_mode = VOIDmode;
+/* If non-zero, implicit "omp declare target" attribute is added into the
+ attribute lists. */
+int current_omp_declare_target_attribute;
/* Each c_binding structure describes one binding of an identifier to
a decl. All the decls in a scope - irrespective of namespace - are
@@ -3974,6 +3977,35 @@ groktypename (struct c_type_name *type_n
return type;
}
+/* Wrapper for decl_attributes that adds some implicit attributes
+ to VAR_DECLs or FUNCTION_DECLs. */
+
+static tree
+c_decl_attributes (tree *node, tree attributes, int flags)
+{
+ /* Add implicit "omp declare target" attribute if requested. */
+ if (current_omp_declare_target_attribute
+ && ((TREE_CODE (*node) == VAR_DECL && TREE_STATIC (*node))
+ || TREE_CODE (*node) == FUNCTION_DECL))
+ {
+ if (TREE_CODE (*node) == VAR_DECL
+ && ((DECL_CONTEXT (*node)
+ && TREE_CODE (DECL_CONTEXT (*node)) == FUNCTION_DECL)
+ || (current_function_decl && !DECL_EXTERNAL (*node))))
+ error ("%q+D in block scope inside of declare target directive",
+ *node);
+ else if (TREE_CODE (*node) == VAR_DECL
+ && !COMPLETE_TYPE_P (TREE_TYPE (*node)))
+ error ("%q+D in declare target directive does not have mappable type",
+ *node);
+ else
+ attributes = tree_cons (get_identifier ("omp declare target"),
+ NULL_TREE, attributes);
+ }
+ return decl_attributes (node, attributes, flags);
+}
+
+
/* Decode a declarator in an ordinary declaration or data definition.
This is called as soon as the type information and variable name
have been parsed, before parsing the initializer if any.
@@ -4108,7 +4140,7 @@ start_decl (struct c_declarator *declara
DECL_COMMON (decl) = 1;
/* Set attributes here so if duplicate decl, will have proper attributes. */
- decl_attributes (&decl, attributes, 0);
+ c_decl_attributes (&decl, attributes, 0);
/* Handle gnu_inline attribute. */
if (declspecs->inline_p
@@ -7724,7 +7756,7 @@ start_function (struct c_declspecs *decl
loc = DECL_SOURCE_LOCATION (decl1);
- decl_attributes (&decl1, attributes, 0);
+ c_decl_attributes (&decl1, attributes, 0);
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
--- gcc/c/c-typeck.c.jj 2013-07-03 22:15:07.000000000 +0200
+++ gcc/c/c-typeck.c 2013-07-06 18:24:50.762931048 +0200
@@ -10730,6 +10730,435 @@ c_finish_omp_cancellation_point (locatio
add_stmt (stmt);
}
+/* Helper function for handle_omp_array_sections. Called recursively
+ to handle multiple array-section-subscripts. C is the clause,
+ T current expression (initially OMP_CLAUSE_DECL), which is either
+ a TREE_LIST for array-section-subscript (TREE_PURPOSE is low-bound
+ expression if specified, TREE_VALUE length expression if specified,
+ TREE_CHAIN is what it has been specified after, or some decl.
+ TYPES vector is populated with array section types, MAYBE_ZERO_LEN
+ set to true if any of the array-section-subscript could have length
+ of zero (explicit or implicit), FIRST_NON_ONE is the index of the
+ first array-section-subscript which is known not to have length
+ of one. Given say:
+ map(a[:b][2:1][:c][:2][:d][e:f][2:5])
+ FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c]
+ all are or may have length of 1, array-section-subscript [:2] is the
+ first one knonwn not to have length 1. For array-section-subscript
+ <= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't
+ 0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we
+ can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above
+ case though, as some lengths could be zero. */
+
+static tree
+handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
+ bool &maybe_zero_len, unsigned int &first_non_one,
+ bool &pointer_based_p)
+{
+ tree ret, low_bound, length, type;
+ if (TREE_CODE (t) != TREE_LIST)
+ {
+ if (t == error_mark_node || TREE_TYPE (t) == error_mark_node)
+ return error_mark_node;
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (POINTER_TYPE_P (TREE_TYPE (t))
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
+ pointer_based_p = true;
+ return t;
+ }
+
+ ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
+ maybe_zero_len, first_non_one,
+ pointer_based_p);
+ if (ret == error_mark_node || ret == NULL_TREE)
+ return ret;
+
+ type = TREE_TYPE (ret);
+ low_bound = TREE_PURPOSE (t);
+ length = TREE_VALUE (t);
+
+ if (low_bound == error_mark_node || length == error_mark_node)
+ return error_mark_node;
+
+ if (low_bound && !INTEGRAL_TYPE_P (TREE_TYPE (low_bound)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "low bound %qE of array section does not have integral type",
+ low_bound);
+ return error_mark_node;
+ }
+ if (length && !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "length %qE of array section does not have integral type",
+ length);
+ return error_mark_node;
+ }
+ if (low_bound
+ && TREE_CODE (low_bound) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (low_bound))
+ > TYPE_PRECISION (sizetype))
+ low_bound = fold_convert (sizetype, low_bound);
+ if (length
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (length))
+ > TYPE_PRECISION (sizetype))
+ length = fold_convert (sizetype, length);
+ if (low_bound == NULL_TREE)
+ low_bound = integer_zero_node;
+
+ if (length != NULL_TREE)
+ {
+ if (!integer_nonzerop (length))
+ maybe_zero_len = true;
+ if (first_non_one == types.length ()
+ && (TREE_CODE (length) != INTEGER_CST || integer_onep (length)))
+ first_non_one++;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (length == NULL_TREE
+ && (TYPE_DOMAIN (type) == NULL_TREE
+ || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for unknown bound array type length expression is "
+ "not optional");
+ return error_mark_node;
+ }
+ if (TREE_CODE (low_bound) == INTEGER_CST
+ && tree_int_cst_sgn (low_bound) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative low bound in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && tree_int_cst_sgn (length) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative length in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ == INTEGER_CST)
+ {
+ tree size = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ size_one_node);
+ if (TREE_CODE (low_bound) == INTEGER_CST)
+ {
+ if (tree_int_cst_lt (size, low_bound))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "low bound %qE above array section size "
+ "in %qs clause", low_bound,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (tree_int_cst_equal (size, low_bound))
+ maybe_zero_len = true;
+ else if (length == NULL_TREE
+ && first_non_one == types.length ()
+ && tree_int_cst_equal
+ (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ low_bound))
+ first_non_one++;
+ }
+ else if (length == NULL_TREE)
+ {
+ maybe_zero_len = true;
+ if (first_non_one == types.length ())
+ first_non_one++;
+ }
+ if (length && TREE_CODE (length) == INTEGER_CST)
+ {
+ if (tree_int_cst_lt (size, length))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "length %qE above array section size "
+ "in %qs clause", length,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (TREE_CODE (low_bound) == INTEGER_CST)
+ {
+ tree lbpluslen
+ = size_binop (PLUS_EXPR,
+ fold_convert (sizetype, low_bound),
+ fold_convert (sizetype, length));
+ if (TREE_CODE (lbpluslen) == INTEGER_CST
+ && tree_int_cst_lt (size, lbpluslen))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "high bound %qE above array section size "
+ "in %qs clause", lbpluslen,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ }
+ }
+ else if (length == NULL_TREE)
+ {
+ maybe_zero_len = true;
+ if (first_non_one == types.length ())
+ first_non_one++;
+ }
+
+ /* For [lb:] we will need to evaluate lb more than once. */
+ if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ {
+ tree lb = c_save_expr (low_bound);
+ if (lb != low_bound)
+ {
+ TREE_PURPOSE (t) = lb;
+ low_bound = lb;
+ }
+ }
+ }
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ if (length == NULL_TREE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for pointer type length expression is not optional");
+ return error_mark_node;
+ }
+ /* If there is a pointer type anywhere but in the very first
+ array-section-subscript, the array section can't be contiguous. */
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have pointer or array type", ret);
+ return error_mark_node;
+ }
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ types.safe_push (TREE_TYPE (ret));
+ /* For pointer based array sections we will need to evaluate lb more
+ than once. */
+ if (pointer_based_p)
+ {
+ tree lb = c_save_expr (low_bound);
+ if (lb != low_bound)
+ {
+ TREE_PURPOSE (t) = lb;
+ low_bound = lb;
+ }
+ }
+ ret = build_array_ref (OMP_CLAUSE_LOCATION (c), ret, low_bound);
+ return ret;
+}
+
+/* Handle array sections for clause C. */
+
+static bool
+handle_omp_array_sections (tree c)
+{
+ bool maybe_zero_len = false;
+ bool pointer_based_p = false;
+ unsigned int first_non_one = 0;
+ vec<tree> types = vNULL;
+ tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+ maybe_zero_len, first_non_one,
+ pointer_based_p);
+ if (first == error_mark_node)
+ {
+ types.release ();
+ return true;
+ }
+ if (first == NULL_TREE)
+ {
+ types.release ();
+ return false;
+ }
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ tree tem = NULL_TREE;
+ types.release ();
+ /* Need to evaluate side effects in the length expressions
+ if any. */
+ while (TREE_CODE (t) == TREE_LIST)
+ {
+ if (TREE_VALUE (t) && TREE_SIDE_EFFECTS (TREE_VALUE (t)))
+ {
+ if (tem == NULL_TREE)
+ tem = TREE_VALUE (t);
+ else
+ tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem),
+ TREE_VALUE (t), tem);
+ }
+ t = TREE_CHAIN (t);
+ }
+ if (tem)
+ first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
+ OMP_CLAUSE_DECL (c) = first;
+ }
+ else
+ {
+ unsigned int num = types.length (), i;
+ tree t, side_effects = NULL_TREE, size = NULL_TREE;
+ tree condition = NULL_TREE;
+
+ if (int_size_in_bytes (TREE_TYPE (first)) <= 0)
+ maybe_zero_len = true;
+
+ for (i = num, t = OMP_CLAUSE_DECL (c); i > 0;
+ t = TREE_CHAIN (t))
+ {
+ tree low_bound = TREE_PURPOSE (t);
+ tree length = TREE_VALUE (t);
+
+ i--;
+ if (low_bound
+ && TREE_CODE (low_bound) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (low_bound))
+ > TYPE_PRECISION (sizetype))
+ low_bound = fold_convert (sizetype, low_bound);
+ if (length
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (length))
+ > TYPE_PRECISION (sizetype))
+ length = fold_convert (sizetype, length);
+ if (low_bound == NULL_TREE)
+ low_bound = integer_zero_node;
+ if (!maybe_zero_len && i > first_non_one)
+ {
+ if (integer_nonzerop (low_bound))
+ goto do_warn_noncontiguous;
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_DOMAIN (types[i])
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (types[i]))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])))
+ == INTEGER_CST)
+ {
+ tree size;
+ size = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
+ size_one_node);
+ if (!tree_int_cst_equal (length, size))
+ {
+ do_warn_noncontiguous:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs "
+ "clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ types.release ();
+ return true;
+ }
+ }
+ if (length != NULL_TREE
+ && TREE_SIDE_EFFECTS (length))
+ {
+ if (side_effects == NULL_TREE)
+ side_effects = length;
+ else
+ side_effects = build2 (COMPOUND_EXPR,
+ TREE_TYPE (side_effects),
+ length, side_effects);
+ }
+ }
+ else
+ {
+ tree l;
+
+ if (i > first_non_one && length && integer_nonzerop (length))
+ continue;
+ if (length)
+ l = fold_convert (sizetype, length);
+ else
+ {
+ l = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
+ size_one_node);
+ l = size_binop (MINUS_EXPR, l,
+ fold_convert (sizetype, low_bound));
+ }
+ if (i > first_non_one)
+ {
+ l = fold_build2 (NE_EXPR, boolean_type_node, l,
+ size_zero_node);
+ if (condition == NULL_TREE)
+ condition = l;
+ else
+ condition = fold_build2 (BIT_AND_EXPR, boolean_type_node,
+ l, condition);
+ }
+ else if (size == NULL_TREE)
+ {
+ size = size_in_bytes (TREE_TYPE (types[i]));
+ size = size_binop (MULT_EXPR, size, l);
+ if (condition)
+ size = fold_build3 (COND_EXPR, sizetype, condition,
+ size, size_zero_node);
+ }
+ else
+ size = size_binop (MULT_EXPR, size, l);
+ }
+ }
+ types.release ();
+ if (side_effects)
+ size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
+ OMP_CLAUSE_DECL (c) = first;
+ OMP_CLAUSE_SIZE (c) = size;
+ if (pointer_based_p)
+ {
+ tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
+ OMP_CLAUSE_MAP_KIND (c2) = OMP_CLAUSE_MAP_POINTER;
+ if (!c_mark_addressable (t))
+ return false;
+ OMP_CLAUSE_DECL (c2) = t;
+ t = build_fold_addr_expr (first);
+ t = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
+ build_pointer_type (char_type_node), t);
+ t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
+ ptrdiff_type_node, t,
+ fold_convert_loc (OMP_CLAUSE_LOCATION (c),
+ TREE_TYPE (t),
+ OMP_CLAUSE_DECL (c2)));
+ OMP_CLAUSE_SIZE (c2) = t;
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = c2;
+ }
+ }
+ return false;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
@@ -10954,21 +11383,49 @@ c_finish_omp_clauses (tree clauses)
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 (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c))
+ remove = true;
+ break;
+ }
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE is not a variable in %<depend%> clause", t);
remove = true;
}
+ else if (!c_mark_addressable (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 (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c))
+ remove = true;
+ else
+ {
+ t = OMP_CLAUSE_DECL (c);
+ if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section does not have mappable type "
+ "in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ }
+ break;
+ }
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE is not a variable in %qs clause", t,
@@ -10982,6 +11439,24 @@ c_finish_omp_clauses (tree clauses)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (!c_mark_addressable (t))
+ remove = true;
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD does not have a mappable type in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
+ break;
+ else if (bitmap_bit_p (&generic_head, DECL_UID (t)))
+ {
+ error ("%qD appears more than once in motion clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&generic_head, DECL_UID (t));
break;
case OMP_CLAUSE_UNIFORM:
@@ -11013,6 +11488,7 @@ c_finish_omp_clauses (tree clauses)
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_THREAD_LIMIT:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
--- gcc/cp/parser.c.jj 2013-07-03 22:15:07.000000000 +0200
+++ gcc/cp/parser.c 2013-07-06 19:33:15.297030502 +0200
@@ -29745,6 +29745,36 @@ cp_parser_omp_declare_target (cp_parser
static void
cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok)
{
+ const char *p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+ if (strcmp (p, "declare") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+ if (strcmp (p, "target") == 0)
+ cp_lexer_consume_token (parser->lexer);
+ else
+ {
+ cp_parser_error (parser, "expected %<target%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
+ }
+ else
+ {
+ cp_parser_error (parser, "expected %<declare%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
if (!current_omp_declare_target_attribute)
error_at (pragma_tok->location,
@@ -29757,7 +29787,8 @@ cp_parser_omp_end_declare_target (cp_par
/* OpenMP 4.0
#pragma omp declare simd declare-simd-clauses[optseq] new-line
#pragma omp declare reduction (reduction-id : typename-list : expression) \
- identity-clause[opt] new-line */
+ identity-clause[opt] new-line
+ #pragma omp declare target new-line */
static void
cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
@@ -29790,7 +29821,8 @@ cp_parser_omp_declare (cp_parser *parser
return;
}
}
- cp_parser_error (parser, "expected %<simd%> or %<reduction%>");
+ cp_parser_error (parser, "expected %<simd%> or %<reduction%> "
+ "or %<target%>");
cp_parser_require_pragma_eol (parser, pragma_tok);
}
--- gcc/testsuite/c-c++-common/gomp/depend-2.c.jj 2013-06-04 20:55:56.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-2.c 2013-07-06 19:18:19.474914134 +0200
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c++ } } */
+/* { dg-do compile } */
/* { dg-options "-fopenmp" } */
void bar (int a[10][10][10]);
--- gcc/testsuite/c-c++-common/gomp/map-1.c.jj 2013-06-04 20:55:56.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/map-1.c 2013-07-06 19:18:46.161478820 +0200
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c++ } } */
+/* { dg-do compile } */
/* { dg-options "-fopenmp" } */
extern int a[][10], a2[][10];
--- gcc/testsuite/c-c++-common/gomp/depend-1.c.jj 2013-06-04 20:55:56.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-1.c 2013-07-06 19:18:08.434094464 +0200
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c++ } } */
+/* { dg-do compile } */
/* { dg-options "-fopenmp" } */
extern int a[][10], a2[][10];
--- gcc/c-family/c-pragma.h.jj 2013-06-14 18:46:39.000000000 +0200
+++ gcc/c-family/c-pragma.h 2013-07-06 18:32:58.451917415 +0200
@@ -33,42 +33,24 @@ typedef enum pragma_kind {
PRAGMA_OMP_CANCELLATION_POINT,
PRAGMA_OMP_CRITICAL,
PRAGMA_OMP_DECLARE_REDUCTION,
- 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,
- 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_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,
PRAGMA_OMP_TASKWAIT,
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,
--- libgomp/testsuite/libgomp.c/for-3.c.jj 2013-07-06 19:43:08.307165397 +0200
+++ libgomp/testsuite/libgomp.c/for-3.c 2013-07-06 19:44:29.618818923 +0200
@@ -0,0 +1,113 @@
+/* { dg-options "-std=gnu99 -fopenmp" } */
+
+extern void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#pragma omp declare target
+
+#define F distribute
+#define G d
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute
+#define G d_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute parallel for
+#define G dpf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for dist_schedule(static, 128)
+#define G dpf_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd
+#define G dpfs
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd dist_schedule(static, 128)
+#define G dpfs_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#pragma omp end declare target
+
+int
+main ()
+{
+ int err = 0;
+/* FIXME: distribute construct must be closely nested
+ in teams region, but we don't handle target expansions
+ yet. Enable when it works. */
+/* #pragma omp target teams reduction(|:err) */
+ {
+ err |= test_d_normal ();
+ err |= test_d_ds128_normal ();
+ err |= test_ds_normal ();
+ err |= test_ds_ds128_normal ();
+ err |= test_dpf_static ();
+ err |= test_dpf_static32 ();
+ err |= test_dpf_auto ();
+ err |= test_dpf_guided32 ();
+ err |= test_dpf_runtime ();
+ err |= test_dpf_ds128_static ();
+ err |= test_dpf_ds128_static32 ();
+ err |= test_dpf_ds128_auto ();
+ err |= test_dpf_ds128_guided32 ();
+ err |= test_dpf_ds128_runtime ();
+ err |= test_dpfs_static ();
+ err |= test_dpfs_static32 ();
+ err |= test_dpfs_auto ();
+ err |= test_dpfs_guided32 ();
+ err |= test_dpfs_runtime ();
+ err |= test_dpfs_ds128_static ();
+ err |= test_dpfs_ds128_static32 ();
+ err |= test_dpfs_ds128_auto ();
+ err |= test_dpfs_ds128_guided32 ();
+ err |= test_dpfs_ds128_runtime ();
+ }
+ if (err)
+ abort ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c/simd-1.c.jj 2013-07-06 19:41:20.872945458 +0200
+++ libgomp/testsuite/libgomp.c/simd-1.c 2013-07-06 20:22:41.110996196 +0200
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+int b[1024] __attribute__((aligned (32))) = { 1 };
+int k, m;
+struct U { int u; };
+struct V { int v; };
+
+__attribute__((noinline, noclone)) int
+foo (int *p)
+{
+ int i, s = 0;
+ struct U u;
+ struct V v;
+ #pragma omp simd aligned(a, p : 32) linear(k: m + 1) \
+ reduction(+:s) lastprivate(u, v)
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] *= p[i];
+ u.u = p[i] + k;
+ k += m + 1;
+ v.v = p[i] + k;
+ s += p[i] + k;
+ }
+ if (u.u != 36 + 4 + 3 * 1023 || v.v != 36 + 4 + 3 * 1024)
+ abort ();
+ return s;
+}
+
+int
+main ()
+{
+#if __SIZEOF_INT__ >= 4
+ int i;
+ k = 4;
+ m = 2;
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] = i - 512;
+ b[i] = (i - 51) % 39;
+ }
+ int s = foo (b);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i])
+ abort ();
+ }
+ if (k != 4 + 3 * 1024 || s != 1596127)
+ abort ();
+#endif
+ return 0;
+}
--- libgomp/testsuite/libgomp.c/simd-2.c.jj 2013-07-06 19:41:23.902895215 +0200
+++ libgomp/testsuite/libgomp.c/simd-2.c 2013-07-06 19:47:08.878746011 +0200
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+__UINTPTR_TYPE__ arr[1027];
+
+__attribute__((noinline, noclone)) void
+foo ()
+{
+ int i, v;
+ #pragma omp simd private (v) safelen(16)
+ for (i = 0; i < 1027; i++)
+ arr[i] = (__UINTPTR_TYPE__) &v;
+}
+
+int
+main ()
+{
+ int i, j, cnt = 0;
+ __UINTPTR_TYPE__ arr2[16];
+ foo ();
+ for (i = 0; i < 1027; i++)
+ {
+ for (j = 0; j < cnt; j++)
+ if (arr[i] == arr2[j])
+ break;
+ if (j != cnt)
+ continue;
+ if (cnt == 16)
+ abort ();
+ arr2[cnt++] = arr[i];
+ }
+ return 0;
+}
--- libgomp/testsuite/libgomp.c/simd-3.c.jj 2013-07-06 19:41:26.916845206 +0200
+++ libgomp/testsuite/libgomp.c/simd-3.c 2013-07-06 19:48:02.498396227 +0200
@@ -0,0 +1,131 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+int b[1024] __attribute__((aligned (32))) = { 1 };
+unsigned char c[1024] __attribute__((aligned (32))) = { 1 };
+int k, m;
+__UINTPTR_TYPE__ u, u2, u3;
+
+__attribute__((noinline, noclone)) int
+foo (int *p)
+{
+ int i, s = 0, s2 = 0, t, t2;
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s) \
+ lastprivate (t2)
+ for (i = 0; i < 512; i++)
+ {
+ a[i] *= p[i];
+ t2 = k + p[i];
+ k += m + 1;
+ s += p[i] + k;
+ c[i]++;
+ }
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s2) \
+ lastprivate (t, u, u2, u3)
+ for (i = 512; i < 1024; i++)
+ {
+ a[i] *= p[i];
+ k += m + 1;
+ t = k + p[i];
+ u = (__UINTPTR_TYPE__) &k;
+ u2 = (__UINTPTR_TYPE__) &s2;
+ u3 = (__UINTPTR_TYPE__) &t;
+ s2 += t;
+ c[i]++;
+ }
+ return s + s2 + t + t2;
+}
+
+__attribute__((noinline, noclone)) long int
+bar (int *p, long int n, long int o)
+{
+ long int i, s = 0, s2 = 0, t, t2;
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s) \
+ lastprivate (t2)
+ for (i = 0; i < n; i++)
+ {
+ a[i] *= p[i];
+ t2 = k + p[i];
+ k += m + 1;
+ s += p[i] + k;
+ c[i]++;
+ }
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s2) \
+ lastprivate (t, u, u2, u3)
+ for (i = n; i < o; i++)
+ {
+ a[i] *= p[i];
+ k += m + 1;
+ t = k + p[i];
+ u = (__UINTPTR_TYPE__) &k;
+ u2 = (__UINTPTR_TYPE__) &s2;
+ u3 = (__UINTPTR_TYPE__) &t;
+ s2 += t;
+ c[i]++;
+ }
+ return s + s2 + t + t2;
+}
+
+int
+main ()
+{
+#if __SIZEOF_INT__ >= 4
+ int i;
+ k = 4;
+ m = 2;
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] = i - 512;
+ b[i] = (i - 51) % 39;
+ c[i] = (unsigned char) i;
+ }
+ int s = foo (b);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 1))
+ abort ();
+ a[i] = i - 512;
+ }
+ if (k != 4 + 3 * 1024
+ || s != 1596127 + (4 + 3 * 511 + b[511]) + (4 + 3 * 1024 + b[1023]))
+ abort ();
+ k = 4;
+ s = bar (b, 512, 1024);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 2))
+ abort ();
+ a[i] = i - 512;
+ }
+ if (k != 4 + 3 * 1024
+ || s != 1596127 + (4 + 3 * 511 + b[511]) + (4 + 3 * 1024 + b[1023]))
+ abort ();
+ k = 4;
+ s = bar (b, 511, 1021);
+ for (i = 0; i < 1021; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 3))
+ abort ();
+ a[i] = i - 512;
+ }
+ for (i = 1021; i < 1024; i++)
+ if (b[i] != (i - 51) % 39
+ || a[i] != i - 512
+ || c[i] != (unsigned char) (i + 2))
+ abort ();
+ if (k != 4 + 3 * 1021
+ || s != 1586803 + (4 + 3 * 510 + b[510]) + (4 + 3 * 1021 + b[1020]))
+ abort ();
+#endif
+ return 0;
+}
Jakub