+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-core.h (enum omp_clause_depend_kind): Add
+ OMP_CLAUSE_DEPEND_UNSPECIFIED.
+ * gimplify.c (gimplify_omp_depend): If there are any
+ OMP_CLAUSE_DEPEND_UNSPECIFIED or OMP_CLAUSE_DEPEND_MUTEXINOUTSET
+ depend clauses, use a new array format.
+ * omp-low.c (lower_depend_clauses): Likewise.
+ * tree-pretty-print.c (dump_omp_clause): Handle
+ OMP_CLAUSE_DEPEND_UNSPECIFIED.
+
2018-06-19 Jakub Jelinek <jakub@redhat.com>
* gimple.h (enum gf_mask): Add GF_OMP_TASK_TASKWAIT.
+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_DEPOBJ.
+ * c-pragma.c (omp_pragmas): Likewise.
+ * c-common.h (c_omp_depend_t_p, c_finish_omp_depobj): Declare.
+ * c-omp.c (c_omp_depend_t_p, c_finish_omp_depobj): New functions.
+
2018-06-19 Jakub Jelinek <jakub@redhat.com>
* c-common.h (c_finish_omp_flush): Add MO argument.
extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
tree, tree, tree, tree, tree, bool,
enum omp_memory_order, bool = false);
+extern bool c_omp_depend_t_p (tree);
+extern void c_finish_omp_depobj (location_t, tree, enum omp_clause_depend_kind,
+ tree);
extern void c_finish_omp_flush (location_t, int);
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
#include "c-common.h"
#include "gimple-expr.h"
#include "c-pragma.h"
+#include "stringpool.h"
#include "omp-general.h"
#include "gomp-constants.h"
#include "memmodel.h"
}
+/* Return true if TYPE is the implementation's omp_depend_t. */
+
+bool
+c_omp_depend_t_p (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ return (TREE_CODE (type) == RECORD_TYPE
+ && TYPE_NAME (type)
+ && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
+ == get_identifier ("omp_depend_t"))
+ && (!TYPE_CONTEXT (type)
+ || TREE_CODE (TYPE_CONTEXT (type)) == TRANSLATION_UNIT_DECL)
+ && COMPLETE_TYPE_P (type)
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && !compare_tree_int (TYPE_SIZE (type),
+ 2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
+}
+
+
+/* Complete a #pragma omp depobj construct. LOC is the location of the
+ #pragma. */
+
+void
+c_finish_omp_depobj (location_t loc, tree depobj,
+ enum omp_clause_depend_kind kind, tree clause)
+{
+ tree t = NULL_TREE;
+ if (!error_operand_p (depobj))
+ {
+ if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
+ {
+ error_at (EXPR_LOC_OR_LOC (depobj, loc),
+ "type of %<depobj%> expression is not %<omp_depend_t%>");
+ depobj = error_mark_node;
+ }
+ else if (TYPE_READONLY (TREE_TYPE (depobj)))
+ {
+ error_at (EXPR_LOC_OR_LOC (depobj, loc),
+ "%<const%> qualified %<depobj%> expression");
+ depobj = error_mark_node;
+ }
+ }
+ else
+ depobj = error_mark_node;
+
+ if (clause == error_mark_node)
+ return;
+
+ if (clause)
+ {
+ gcc_assert (TREE_CODE (clause) == OMP_CLAUSE
+ && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
+ if (OMP_CLAUSE_CHAIN (clause))
+ error_at (OMP_CLAUSE_LOCATION (clause),
+ "more than one locator in %<depend%> clause on %<depobj%> "
+ "construct");
+ switch (OMP_CLAUSE_DEPEND_KIND (clause))
+ {
+ case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+ error_at (OMP_CLAUSE_LOCATION (clause),
+ "dependence type must be specified in %<depend%> clause "
+ "on %<depobj%> construct");
+ return;
+ case OMP_CLAUSE_DEPEND_SOURCE:
+ case OMP_CLAUSE_DEPEND_SINK:
+ error_at (OMP_CLAUSE_LOCATION (clause),
+ "%<depend(%s)%> is only allowed in %<omp ordered%>",
+ OMP_CLAUSE_DEPEND_KIND (clause) == OMP_CLAUSE_DEPEND_SOURCE
+ ? "source" : "sink");
+ return;
+ case OMP_CLAUSE_DEPEND_IN:
+ case OMP_CLAUSE_DEPEND_OUT:
+ case OMP_CLAUSE_DEPEND_INOUT:
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ kind = OMP_CLAUSE_DEPEND_KIND (clause);
+ t = OMP_CLAUSE_DECL (clause);
+ gcc_assert (t);
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ error_at (OMP_CLAUSE_LOCATION (clause),
+ "%<iterator%> modifier may not be specified on "
+ "%<depobj%> construct");
+ return;
+ }
+ if (TREE_CODE (t) == COMPOUND_EXPR)
+ {
+ tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
+ t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
+ t1);
+ }
+ else
+ t = build_fold_addr_expr (t);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ gcc_assert (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED);
+
+ if (depobj == error_mark_node)
+ return;
+
+ depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
+ tree dtype
+ = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
+ true);
+ depobj = fold_convert (dtype, depobj);
+ tree r;
+ if (clause)
+ {
+ depobj = save_expr (depobj);
+ r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
+ add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
+ }
+ int k;
+ switch (kind)
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ k = GOMP_DEPEND_IN;
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ k = GOMP_DEPEND_OUT;
+ break;
+ case OMP_CLAUSE_DEPEND_INOUT:
+ k = GOMP_DEPEND_INOUT;
+ break;
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ k = GOMP_DEPEND_MUTEXINOUTSET;
+ break;
+ case OMP_CLAUSE_DEPEND_LAST:
+ k = -1;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ t = build_int_cst (ptr_type_node, k);
+ depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
+ TYPE_SIZE_UNIT (ptr_type_node));
+ r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
+ add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
+}
+
+
/* Complete a #pragma omp flush construct. We don't do anything with
the variable list that the syntax allows. LOC is the location of
the #pragma. */
{ "cancel", PRAGMA_OMP_CANCEL },
{ "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
{ "critical", PRAGMA_OMP_CRITICAL },
+ { "depobj", PRAGMA_OMP_DEPOBJ },
{ "end", PRAGMA_OMP_END_DECLARE_TARGET },
{ "flush", PRAGMA_OMP_FLUSH },
{ "master", PRAGMA_OMP_MASTER },
PRAGMA_OMP_CANCELLATION_POINT,
PRAGMA_OMP_CRITICAL,
PRAGMA_OMP_DECLARE,
+ PRAGMA_OMP_DEPOBJ,
PRAGMA_OMP_DISTRIBUTE,
PRAGMA_OMP_END_DECLARE_TARGET,
PRAGMA_OMP_FLUSH,
+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_depobj): New function.
+ (c_parser_pragma): Handle PRAGMA_OMP_DEPOBJ.
+ (c_parser_omp_iterators): Return error_mark_node instead of NULL.
+ (c_parser_omp_clause_depend): Make dependence-type optional.
+ * c-typeck.c (c_finish_omp_clauses): Handle depend clause with
+ OMP_CLAUSE_DEPEND_UNSPECIFIED. Diagnose bit-fields. Require
+ omp_depend_t type for OMP_CLAUSE_DEPEND_UNSPECIFIED kinds and
+ some different type for other kinds. Use build_unary_op with
+ ADDR_EXPR and build_indirect_ref instead of c_mark_addressable.
+
2018-06-19 Jakub Jelinek <jakub@redhat.com>
* c-parser.c: Include memmodel.h.
static void c_parser_omp_construct (c_parser *, bool *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
+static void c_parser_omp_depobj (c_parser *);
static void c_parser_omp_flush (c_parser *);
static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
tree, tree *, bool *);
c_parser_omp_barrier (parser);
return false;
+ case PRAGMA_OMP_DEPOBJ:
+ if (context != pragma_compound)
+ {
+ construct = "omp depobj";
+ goto in_compound;
+ }
+ c_parser_omp_depobj (parser);
+ return false;
+
case PRAGMA_OMP_FLUSH:
if (context != pragma_compound)
{
while (1);
parens.skip_until_found_close (parser);
- return ret;
+ return ret ? ret : error_mark_node;
}
/* OpenMP 4.0:
c_parser_omp_clause_depend (c_parser *parser, tree list)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
tree nl, c, iterators = NULL_TREE;
matching_parens parens;
do
{
if (c_parser_next_token_is_not (parser, CPP_NAME))
- goto invalid_kind;
+ break;
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp ("iterator", p) == 0
+ && iterators == NULL_TREE
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
+ {
+ /* FIXME: if depend kind remains optional, this is ambiguous
+ and we'd need to do tentative parsing to distinguish between
+ valid iterator modifier and just normal expression starting
+ with iterator ( tokens. Not doing it right now, as I hope
+ it will become mandatory. */
+ iterators = c_parser_omp_iterators (parser);
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+ continue;
+ }
+ if (strcmp ("source", p) == 0
+ && c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN)
+ {
+ /* FIXME: this is another ambiguity. */
+ kind = OMP_CLAUSE_DEPEND_SOURCE;
+ break;
+ }
+ if (c_parser_peek_2nd_token (parser)->type != CPP_COLON)
+ break;
if (strcmp ("in", p) == 0)
kind = OMP_CLAUSE_DEPEND_IN;
else if (strcmp ("inout", p) == 0)
kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
else if (strcmp ("out", p) == 0)
kind = OMP_CLAUSE_DEPEND_OUT;
- else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
else if (strcmp ("sink", p) == 0)
kind = OMP_CLAUSE_DEPEND_SINK;
- else if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
- {
- iterators = c_parser_omp_iterators (parser);
- c_parser_require (parser, CPP_COLON, "expected %<:%>");
- continue;
- }
else
goto invalid_kind;
break;
}
while (1);
- c_parser_consume_token (parser);
+ if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ c_parser_consume_token (parser);
if (iterators
&& (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
return c;
}
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED
+ && !c_parser_require (parser, CPP_COLON, "expected %<:%>"))
goto resync_fail;
if (kind == OMP_CLAUSE_DEPEND_SINK)
return c_finish_omp_critical (loc, stmt, name, clauses);
}
+/* OpenMP 5.0:
+ # pragma omp depobj ( depobj ) depobj-clause new-line
+
+ depobj-clause:
+ depend (dependence-type : locator)
+ destroy
+ update (dependence-type)
+
+ dependence-type:
+ in
+ out
+ inout
+ mutexinout */
+
+static void
+c_parser_omp_depobj (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+
+ tree depobj = c_parser_expr_no_commas (parser, NULL).value;
+ if (depobj != error_mark_node)
+ {
+ if (!lvalue_p (depobj))
+ {
+ error_at (EXPR_LOC_OR_LOC (depobj, loc),
+ "%<depobj%> expression is not lvalue expression");
+ depobj = error_mark_node;
+ }
+ else
+ {
+ tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
+ depobj, false);
+ if (addr == error_mark_node)
+ depobj = error_mark_node;
+ else
+ depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
+ addr, RO_UNARY_STAR);
+ }
+ }
+
+ parens.skip_until_found_close (parser);
+ tree clause = NULL_TREE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
+ location_t c_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ c_parser_consume_token (parser);
+ if (!strcmp ("depend", p))
+ {
+ clause = c_parser_omp_clause_depend (parser, NULL_TREE);
+ clause = c_finish_omp_clauses (clause, C_ORT_OMP);
+ if (!clause)
+ clause = error_mark_node;
+ }
+ else if (!strcmp ("destroy", p))
+ kind = OMP_CLAUSE_DEPEND_LAST;
+ else if (!strcmp ("update", p))
+ {
+ matching_parens c_parens;
+ if (c_parens.require_open (parser))
+ {
+ location_t c2_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p2
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ c_parser_consume_token (parser);
+ if (!strcmp ("in", p2))
+ kind = OMP_CLAUSE_DEPEND_IN;
+ else if (!strcmp ("out", p2))
+ kind = OMP_CLAUSE_DEPEND_OUT;
+ else if (!strcmp ("inout", p2))
+ kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (!strcmp ("mutexinoutset", p2))
+ kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+ }
+ if (kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ clause = error_mark_node;
+ error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
+ "%<mutexinoutset%>");
+ }
+ c_parens.skip_until_found_close (parser);
+ }
+ else
+ clause = error_mark_node;
+ }
+ }
+ if (!clause && kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ clause = error_mark_node;
+ error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
+ }
+ c_parser_skip_to_pragma_eol (parser);
+
+ c_finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+
/* OpenMP 2.5:
# pragma omp flush flush-vars[opt] new-line
{
if (handle_omp_array_sections (c, ort))
remove = true;
+ else if (OMP_CLAUSE_DEPEND_KIND (c)
+ == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<depend%> clause without dependence type "
+ "on array section");
+ remove = true;
+ }
break;
}
if (t == error_mark_node)
"%<depend%> clause", t);
remove = true;
}
- else if (!c_mark_addressable (t))
- remove = true;
+ else if (TREE_CODE (t) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (t, 1)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "bit-field %qE in %qs clause", t, "depend");
+ remove = true;
+ }
+ else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ if (!c_omp_depend_t_p (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have %<omp_depend_t%> type in "
+ "%<depend%> clause without dependence type", t);
+ remove = true;
+ }
+ }
+ else if (c_omp_depend_t_p (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE should not have %<omp_depend_t%> type in "
+ "%<depend%> clause with dependence type", t);
+ remove = true;
+ }
+ if (!remove)
+ {
+ tree addr = build_unary_op (OMP_CLAUSE_LOCATION (c), ADDR_EXPR,
+ t, false);
+ if (addr == error_mark_node)
+ remove = true;
+ else
+ {
+ t = build_indirect_ref (OMP_CLAUSE_LOCATION (c), addr,
+ RO_UNARY_STAR);
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+ && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+ && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+ == TREE_VEC))
+ TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+ else
+ OMP_CLAUSE_DECL (c) = t;
+ }
+ }
break;
case OMP_CLAUSE_MAP:
+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_var_list_no_open): Fix up depend clause
+ error recovery.
+ (cp_parser_omp_iterators): Return error_mark_node instead of NULL.
+ (cp_parser_omp_clause_depend): Make dependence-type optional.
+ (cp_parser_omp_depobj): New function.
+ (cp_parser_pragma): Handle PRAGMA_OMP_DEPOBJ.
+ * cp-tree.h (OMP_DEPOBJ_DEPOBJ, OMP_DEPOBJ_CLAUSES): Define.
+ (finish_omp_depobj): Declare.
+ * cp-tree.def (OMP_DEPOBJ): New tree code.
+ * semantics.c (finish_omp_clauses): Handle depend clause with
+ OMP_CLAUSE_DEPEND_UNSPECIFIED. Diagnose bit-fields. Require
+ omp_depend_t type for OMP_CLAUSE_DEPEND_UNSPECIFIED kinds and
+ some different type for other kinds. Use cp_build_addr_expr
+ and cp_build_indirect_ref instead of cxx_mark_addressable.
+ (finish_omp_depobj): New function.
+ * pt.c (tsubst_expr): Handle OMP_DEPOBJ.
+ * cp-objcp-common.c (cp_common_init_ts): Likewise.
+ * constexpr.c (potential_constant_expression_1): Likewise.
+ * lex.c (cxx_init): Likewise.
+ * dump.c (cp_dump_tree): Likewise.
+ * cxx-pretty-print.c (cxx_pretty_printer::statement): Likewise.
+
2018-06-19 Jakub Jelinek <jakub@redhat.com>
* cp-tree.h (finish_omp_flush): Add MO argument.
case OMP_ATOMIC_READ:
case OMP_ATOMIC_CAPTURE_OLD:
case OMP_ATOMIC_CAPTURE_NEW:
+ case OMP_DEPOBJ:
case OACC_PARALLEL:
case OACC_KERNELS:
case OACC_DATA:
MARK_TS_TYPED (UNARY_RIGHT_FOLD_EXPR);
MARK_TS_TYPED (BINARY_LEFT_FOLD_EXPR);
MARK_TS_TYPED (BINARY_RIGHT_FOLD_EXPR);
+ MARK_TS_TYPED (OMP_DEPOBJ);
}
#include "gt-cp-cp-objcp-common.h"
instantiation time. */
DEFTREECODE (TEMPLATE_INFO, "template_info", tcc_exceptional, 0)
+/* OpenMP - #pragma omp depobj
+ Operand 0: OMP_DEPOBJ_DEPOBJ: Depobj expression
+ Operand 1: OMP_DEPOBJ_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_DEPOBJ, "omp_depobj", tcc_statement, 2)
+
/* Extensions for Concepts. */
/* Used to represent information associated with constrained declarations. */
#define ALIGNOF_EXPR_STD_P(NODE) \
TREE_LANG_FLAG_0 (ALIGNOF_EXPR_CHECK (NODE))
+/* OMP_DEPOBJ accessors. These give access to the depobj expression of the
+ #pragma omp depobj directive and the clauses, respectively. If
+ OMP_DEPOBJ_CLAUSES is INTEGER_CST, it is instead the update clause kind
+ or OMP_CLAUSE_DEPEND_LAST for destroy clause. */
+#define OMP_DEPOBJ_DEPOBJ(NODE) TREE_OPERAND (OMP_DEPOBJ_CHECK (NODE), 0)
+#define OMP_DEPOBJ_CLAUSES(NODE) TREE_OPERAND (OMP_DEPOBJ_CHECK (NODE), 1)
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types {
none_type = 0, /* Not a tag type. */
tree, tree, tree, tree, tree,
tree, enum omp_memory_order);
extern void finish_omp_barrier (void);
+extern void finish_omp_depobj (location_t, tree,
+ enum omp_clause_depend_kind,
+ tree);
extern void finish_omp_flush (int);
extern void finish_omp_taskwait (void);
extern void finish_omp_taskyield (void);
declaration (t);
break;
+ case OMP_DEPOBJ:
+ pp_cxx_ws_string (this, "#pragma omp depobj");
+ pp_space (this);
+ pp_cxx_left_paren (this);
+ expression (OMP_DEPOBJ_DEPOBJ (t));
+ pp_cxx_right_paren (this);
+ if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
+ {
+ if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
+ dump_omp_clauses (this, OMP_DEPOBJ_CLAUSES (t),
+ pp_indentation (this), 0);
+ else
+ switch (tree_to_uhwi (OMP_DEPOBJ_CLAUSES (t)))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ pp_cxx_ws_string (this, " update(in)");
+ break;
+ case OMP_CLAUSE_DEPEND_INOUT:
+ pp_cxx_ws_string (this, " update(inout)");
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ pp_cxx_ws_string (this, " update(out)");
+ break;
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ pp_cxx_ws_string (this, " update(mutexinoutset)");
+ break;
+ case OMP_CLAUSE_DEPEND_LAST:
+ pp_cxx_ws_string (this, " destroy");
+ break;
+ default:
+ break;
+ }
+ }
+ pp_needs_newline (this) = true;
+ break;
+
default:
c_pretty_printer::statement (t);
break;
dump_child ("expr", EXPR_STMT_EXPR (t));
break;
+ case OMP_DEPOBJ:
+ dump_stmt (di, t);
+ dump_child ("depobj", OMP_DEPOBJ_DEPOBJ (t));
+ dump_child ("clauses", OMP_DEPOBJ_CLAUSES (t));
+ break;
+
default:
break;
}
IF_STMT, CLEANUP_STMT, FOR_STMT,
RANGE_FOR_STMT, WHILE_STMT, DO_STMT,
BREAK_STMT, CONTINUE_STMT, SWITCH_STMT,
- EXPR_STMT
+ EXPR_STMT, OMP_DEPOBJ
};
memset (&statement_code_p, 0, sizeof (statement_code_p));
else
decl = name;
if (decl == error_mark_node)
- cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
- token->location);
+ {
+ if (kind == OMP_CLAUSE_DEPEND
+ && cp_parser_simulate_error (parser))
+ goto depend_lvalue;
+ cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
+ token->location);
+ }
}
if (decl == error_mark_node)
;
/*or_comma=*/false,
/*consume_paren=*/true);
- return ret;
+ return ret ? ret : error_mark_node;
}
/* OpenMP 4.0:
cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
{
tree nlist, c, iterators = NULL_TREE;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
matching_parens parens;
if (!parens.require_open (parser))
do
{
if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
- goto invalid_kind;
+ break;
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp ("iterator", p) == 0
+ && iterators == NULL_TREE
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+ {
+ cp_lexer_save_tokens (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ bool is_iter
+ = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
+ /*consume_paren=*/true)
+ && cp_lexer_next_token_is (parser->lexer, CPP_COLON));
+
+ /* Roll back the tokens we skipped. */
+ cp_lexer_rollback_tokens (parser->lexer);
+
+ if (is_iter)
+ {
+ begin_scope (sk_omp, NULL);
+ iterators = cp_parser_omp_iterators (parser);
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ continue;
+ }
+ }
+ if (strcmp ("source", p) == 0
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN))
+ {
+ /* FIXME: this is ambiguous. */
+ kind = OMP_CLAUSE_DEPEND_SOURCE;
+ break;
+ }
+
+ if (!cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ break;
if (strcmp ("in", p) == 0)
kind = OMP_CLAUSE_DEPEND_IN;
else if (strcmp ("inout", p) == 0)
kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
else if (strcmp ("out", p) == 0)
kind = OMP_CLAUSE_DEPEND_OUT;
- else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
else if (strcmp ("sink", p) == 0)
kind = OMP_CLAUSE_DEPEND_SINK;
- else if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
- {
- begin_scope (sk_omp, NULL);
- iterators = cp_parser_omp_iterators (parser);
- cp_parser_require (parser, CPP_COLON, RT_COLON);
- continue;
- }
else
goto invalid_kind;
break;
}
while (1);
- cp_lexer_consume_token (parser->lexer);
+ if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ cp_lexer_consume_token (parser->lexer);
if (iterators
&& (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
return c;
}
- if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED
+ && !cp_parser_require (parser, CPP_COLON, RT_COLON))
goto resync_fail;
if (kind == OMP_CLAUSE_DEPEND_SINK)
return c_finish_omp_critical (input_location, stmt, name, clauses);
}
+/* OpenMP 5.0:
+ # pragma omp depobj ( depobj ) depobj-clause new-line
+
+ depobj-clause:
+ depend (dependence-type : locator)
+ destroy
+ update (dependence-type)
+
+ dependence-type:
+ in
+ out
+ inout
+ mutexinout */
+
+static void
+cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
+{
+ location_t loc = pragma_tok->location;
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
+
+ tree depobj = cp_parser_assignment_expression (parser);
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ tree clause = NULL_TREE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
+ location_t c_loc = cp_lexer_peek_token (parser->lexer)->location;
+ 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);
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!strcmp ("depend", p))
+ {
+ clause = cp_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
+ if (clause)
+ clause = finish_omp_clauses (clause, C_ORT_OMP);
+ if (!clause)
+ clause = error_mark_node;
+ }
+ else if (!strcmp ("destroy", p))
+ kind = OMP_CLAUSE_DEPEND_LAST;
+ else if (!strcmp ("update", p))
+ {
+ matching_parens c_parens;
+ if (c_parens.require_open (parser))
+ {
+ location_t c2_loc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id2 = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p2 = IDENTIFIER_POINTER (id2);
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!strcmp ("in", p2))
+ kind = OMP_CLAUSE_DEPEND_IN;
+ else if (!strcmp ("out", p2))
+ kind = OMP_CLAUSE_DEPEND_OUT;
+ else if (!strcmp ("inout", p2))
+ kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (!strcmp ("mutexinoutset", p2))
+ kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+ }
+ if (kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ clause = error_mark_node;
+ error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
+ "%<mutexinoutset%>");
+ }
+ if (!c_parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ }
+ else
+ clause = error_mark_node;
+ }
+ }
+ if (!clause && kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ clause = error_mark_node;
+ error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
+ }
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+
+ finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+
/* OpenMP 2.5:
# pragma omp flush flush-vars[opt] new-line
}
break;
+ case PRAGMA_OMP_DEPOBJ:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_depobj (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location, "%<#pragma %s%> may only be "
+ "used in compound statements", "omp depobj");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
case PRAGMA_OMP_FLUSH:
switch (context)
{
pop_omp_privatization_clauses (r);
break;
+ case OMP_DEPOBJ:
+ r = RECUR (OMP_DEPOBJ_DEPOBJ (t));
+ if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
+ {
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
+ if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
+ {
+ tmp = tsubst_omp_clauses (OMP_DEPOBJ_CLAUSES (t), C_ORT_OMP,
+ args, complain, in_decl);
+ if (tmp == NULL_TREE)
+ tmp = error_mark_node;
+ }
+ else
+ {
+ kind = (enum omp_clause_depend_kind)
+ tree_to_uhwi (OMP_DEPOBJ_CLAUSES (t));
+ tmp = NULL_TREE;
+ }
+ finish_omp_depobj (EXPR_LOCATION (t), r, kind, tmp);
+ }
+ else
+ finish_omp_depobj (EXPR_LOCATION (t), r,
+ OMP_CLAUSE_DEPEND_UNSPECIFIED,
+ OMP_DEPOBJ_CLAUSES (t));
+ break;
+
case OACC_DATA:
case OMP_TARGET_DATA:
case OMP_TARGET:
{
if (handle_omp_array_sections (c, ort))
remove = true;
+ else if (OMP_CLAUSE_DEPEND_KIND (c)
+ == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<depend%> clause without dependence type "
+ "on array section");
+ remove = true;
+ }
break;
}
if (t == error_mark_node)
"in %<depend%> clause", t);
remove = true;
}
- else if (!cxx_mark_addressable (t))
- remove = true;
+ else if (TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
+ && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "bit-field %qE in %qs clause", t, "depend");
+ remove = true;
+ }
+ else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+ {
+ if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+ ? TREE_TYPE (TREE_TYPE (t))
+ : TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have %<omp_depend_t%> type in "
+ "%<depend%> clause without dependence type", t);
+ remove = true;
+ }
+ }
+ else if (c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+ ? TREE_TYPE (TREE_TYPE (t))
+ : TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE should not have %<omp_depend_t%> type in "
+ "%<depend%> clause with dependence type", t);
+ remove = true;
+ }
+ if (!remove)
+ {
+ tree addr = cp_build_addr_expr (t, tf_warning_or_error);
+ if (addr == error_mark_node)
+ remove = true;
+ else
+ {
+ t = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+ tf_warning_or_error);
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+ && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+ && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+ == TREE_VEC))
+ TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+ else
+ OMP_CLAUSE_DECL (c) = t;
+ }
+ }
break;
case OMP_CLAUSE_MAP:
finish_expr_stmt (stmt);
}
+void
+finish_omp_depobj (location_t loc, tree depobj,
+ enum omp_clause_depend_kind kind, tree clause)
+{
+ if (!error_operand_p (depobj) && !type_dependent_expression_p (depobj))
+ {
+ if (!lvalue_p (depobj))
+ {
+ error_at (EXPR_LOC_OR_LOC (depobj, loc),
+ "%<depobj%> expression is not lvalue expression");
+ depobj = error_mark_node;
+ }
+ }
+
+ if (processing_template_decl)
+ {
+ if (clause == NULL_TREE)
+ clause = build_int_cst (integer_type_node, kind);
+ add_stmt (build_min_nt_loc (loc, OMP_DEPOBJ, depobj, clause));
+ return;
+ }
+
+ if (!error_operand_p (depobj))
+ {
+ tree addr = cp_build_addr_expr (depobj, tf_warning_or_error);
+ if (addr == error_mark_node)
+ depobj = error_mark_node;
+ else
+ depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+ tf_warning_or_error);
+ }
+
+ c_finish_omp_depobj (loc, depobj, kind, clause);
+}
+
void
finish_omp_flush (int mo)
{
{
tree c;
gimple *g;
- size_t n[2] = { 0, 0 };
- tree counts[2] = { NULL_TREE, NULL_TREE };
+ size_t n[4] = { 0, 0, 0, 0 };
+ bool unused[4];
+ tree counts[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
tree last_iter = NULL_TREE, last_count = NULL_TREE;
- size_t i;
+ size_t i, j;
location_t first_loc = UNKNOWN_LOCATION;
for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
switch (OMP_CLAUSE_DEPEND_KIND (c))
{
case OMP_CLAUSE_DEPEND_IN:
- i = 0;
+ i = 2;
break;
case OMP_CLAUSE_DEPEND_OUT:
case OMP_CLAUSE_DEPEND_INOUT:
+ i = 0;
+ break;
case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
i = 1;
break;
+ case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+ i = 3;
+ break;
case OMP_CLAUSE_DEPEND_SOURCE:
case OMP_CLAUSE_DEPEND_SINK:
continue;
else
n[i]++;
}
- if (counts[0] == NULL_TREE && counts[1] == NULL_TREE)
+ for (i = 0; i < 4; i++)
+ if (counts[i])
+ break;
+ if (i == 4)
return 0;
- for (i = 0; i < 2; i++)
+
+ tree total = size_zero_node;
+ for (i = 0; i < 4; i++)
{
+ unused[i] = counts[i] == NULL_TREE && n[i] == 0;
if (counts[i] == NULL_TREE)
counts[i] = size_zero_node;
if (n[i])
if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
fb_rvalue) == GS_ERROR)
return 2;
+ total = size_binop (PLUS_EXPR, total, counts[i]);
}
- tree total = size_binop (PLUS_EXPR, counts[0], counts[1]);
if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
== GS_ERROR)
return 2;
- tree totalp1 = size_binop (PLUS_EXPR, unshare_expr (total), size_int (1));
- tree type = build_array_type (ptr_type_node, build_index_type (totalp1));
+ bool is_old = unused[1] && unused[3];
+ tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
+ size_int (is_old ? 1 : 4));
+ tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
tree array = create_tmp_var_raw (type);
TREE_ADDRESSABLE (array) = 1;
- if (TREE_CODE (totalp1) != INTEGER_CST)
+ if (TREE_CODE (totalpx) != INTEGER_CST)
{
if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
gimplify_type_sizes (TREE_TYPE (array), pre_p);
gimple_add_tmp_var (array);
tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
NULL_TREE);
- tree tem = build2 (MODIFY_EXPR, void_type_node, r,
- fold_convert (ptr_type_node, total));
- gimplify_and_add (tem, pre_p);
- r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
- NULL_TREE);
- tem = build2 (MODIFY_EXPR, void_type_node, r, counts[1]);
+ tree tem;
+ if (!is_old)
+ {
+ tem = build2 (MODIFY_EXPR, void_type_node, r,
+ build_int_cst (ptr_type_node, 0));
+ gimplify_and_add (tem, pre_p);
+ r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
+ NULL_TREE);
+ }
+ tem = build2 (MODIFY_EXPR, void_type_node, r,
+ fold_convert (ptr_type_node, total));
gimplify_and_add (tem, pre_p);
+ for (i = 1; i < (is_old ? 2 : 4); i++)
+ {
+ r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
+ NULL_TREE, NULL_TREE);
+ tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
+ gimplify_and_add (tem, pre_p);
+ }
- tree cnts[2];
- for (i = 0; i < 2; i++)
+ tree cnts[4];
+ for (j = 4; j; j--)
+ if (!unused[j - 1])
+ break;
+ for (i = 0; i < 4; i++)
{
+ if (i && (i >= j || unused[i - 1]))
+ {
+ cnts[i] = cnts[i - 1];
+ continue;
+ }
cnts[i] = create_tmp_var (sizetype, NULL);
- g = gimple_build_assign (cnts[i], i == 0 ? size_int (2)
- : size_binop (PLUS_EXPR, counts[0],
- size_int (2)));
+ if (i == 0)
+ g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
+ else
+ {
+ tree t;
+ if (is_old)
+ t = size_binop (PLUS_EXPR, counts[0], size_int (2));
+ else
+ t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
+ if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
+ == GS_ERROR)
+ return 2;
+ g = gimple_build_assign (cnts[i], t);
+ }
gimple_seq_add_stmt (pre_p, g);
}
switch (OMP_CLAUSE_DEPEND_KIND (c))
{
case OMP_CLAUSE_DEPEND_IN:
- i = 0;
+ i = 2;
break;
case OMP_CLAUSE_DEPEND_OUT:
case OMP_CLAUSE_DEPEND_INOUT:
+ i = 0;
+ break;
case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
i = 1;
break;
+ case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+ i = 3;
+ break;
case OMP_CLAUSE_DEPEND_SOURCE:
case OMP_CLAUSE_DEPEND_SINK:
continue;
}
if (last_bind)
gimplify_and_add (last_bind, pre_p);
- tree cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
- size_binop_loc (first_loc, PLUS_EXPR, counts[0],
- size_int (2)));
- cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
- build2_loc (first_loc, NE_EXPR, boolean_type_node,
- cnts[1],
- size_binop_loc (first_loc, PLUS_EXPR,
- totalp1, size_int (1))));
+ tree cond = boolean_false_node;
+ if (is_old)
+ {
+ if (!unused[0])
+ cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
+ size_binop_loc (first_loc, PLUS_EXPR, counts[0],
+ size_int (2)));
+ if (!unused[2])
+ cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
+ build2_loc (first_loc, NE_EXPR, boolean_type_node,
+ cnts[2],
+ size_binop_loc (first_loc, PLUS_EXPR,
+ totalpx,
+ size_int (1))));
+ }
+ else
+ {
+ tree prev = size_int (5);
+ for (i = 0; i < 4; i++)
+ {
+ if (unused[i])
+ continue;
+ prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
+ cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
+ build2_loc (first_loc, NE_EXPR, boolean_type_node,
+ cnts[i], unshare_expr (prev)));
+ }
+ }
tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
build_call_expr_loc (first_loc,
builtin_decl_explicit (BUILT_IN_TRAP),
{
tree c, clauses;
gimple *g;
- size_t n_in = 0, n_out = 0, idx = 2, i;
+ size_t cnt[4] = { 0, 0, 0, 0 }, idx = 2, i;
clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
gcc_assert (clauses);
/* Lowering already done at gimplification. */
return;
case OMP_CLAUSE_DEPEND_IN:
- n_in++;
+ cnt[2]++;
break;
case OMP_CLAUSE_DEPEND_OUT:
case OMP_CLAUSE_DEPEND_INOUT:
+ cnt[0]++;
+ break;
case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
- n_out++;
+ cnt[1]++;
+ break;
+ case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+ cnt[3]++;
break;
case OMP_CLAUSE_DEPEND_SOURCE:
case OMP_CLAUSE_DEPEND_SINK:
default:
gcc_unreachable ();
}
- tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
+ if (cnt[1] || cnt[3])
+ idx = 5;
+ size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3];
+ tree type = build_array_type_nelts (ptr_type_node, total + idx);
tree array = create_tmp_var (type);
TREE_ADDRESSABLE (array) = 1;
tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
NULL_TREE);
- g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
- gimple_seq_add_stmt (iseq, g);
- r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
- NULL_TREE);
- g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
+ if (idx == 5)
+ {
+ g = gimple_build_assign (r, build_int_cst (ptr_type_node, 0));
+ gimple_seq_add_stmt (iseq, g);
+ r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
+ NULL_TREE);
+ }
+ g = gimple_build_assign (r, build_int_cst (ptr_type_node, total));
gimple_seq_add_stmt (iseq, g);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < (idx == 5 ? 3 : 1); i++)
{
- if ((i ? n_in : n_out) == 0)
+ r = build4 (ARRAY_REF, ptr_type_node, array,
+ size_int (i + 1 + (idx == 5)), NULL_TREE, NULL_TREE);
+ g = gimple_build_assign (r, build_int_cst (ptr_type_node, cnt[i]));
+ gimple_seq_add_stmt (iseq, g);
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (cnt[i] == 0)
continue;
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ continue;
+ else
{
+ switch (OMP_CLAUSE_DEPEND_KIND (c))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ if (i != 2)
+ continue;
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ case OMP_CLAUSE_DEPEND_INOUT:
+ if (i != 0)
+ continue;
+ break;
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ if (i != 1)
+ continue;
+ break;
+ case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+ if (i != 3)
+ continue;
+ break;
+ default:
+ gcc_unreachable ();
+ }
tree t = OMP_CLAUSE_DECL (c);
t = fold_convert (ptr_type_node, t);
gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/depend-6.c: Add test for bit-field in depend
+ clause.
+ * c-c++-common/gomp/depend-iterator-2.c: Adjust for dependence-type
+ being optional.
+ * c-c++-common/gomp/depobj-1.c: New test.
+ * g++.dg/gomp/depend-iterator-2.C: Adjust for dependence-type being
+ optional.
+ * g++.dg/gomp/depobj-1.C: New test.
+
2018-06-19 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/gomp/flush-1.c: New test.
struct T { int c[3]; };
struct S { int a; struct T *b; struct T g; };
+struct U { int a : 5; };
struct S d[10];
struct S *e[10];
struct S *f;
struct S h;
+struct U i;
void
foo (void)
;
#pragma omp task depend(inout: h.g.c[2:1]) /* { dg-error "expected" } */
;
+ #pragma omp task depend(in: i.a) /* { dg-error "bit-field '\[^\n\r]*' in 'depend' clause" } */
+ ;
}
void
f1 (void)
{
- #pragma omp task depend (iterator : in : a) /* { dg-error "expected" } */
+ #pragma omp task depend (iterator : in : a) /* { dg-error "expected|invalid depend kind" } */
;
#pragma omp task depend (iterator (for = 0 : 2) : in : a) /* { dg-error "expected" } */
;
;
#pragma omp task depend (iterator (i = 0 : 10 : 2, 3) : in : a) /* { dg-error "expected" } */
;
- #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a) /* { dg-error "expected ':'|invalid depend kind" } */
- ;
- #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a) /* { dg-error "invalid depend kind" } */
+ #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a) /* { dg-error "expected ':'|invalid depend kind|'iterator' undeclared|was not declared|expected '\\)' before ':' token" } */
;
#pragma omp task depend (iterator (i = 0:32) : in : b[i*2:2])
;
#pragma omp ordered depend (iterator (int l = 0:2:3) : source) /* { dg-error "'iterator' modifier incompatible with 'source'" } */
}
}
+
+void
+f3 (void)
+{
+ #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a) /* { dg-error "invalid depend kind|'iterator' undeclared|was not declared|expected '\\)' before ':' token" } */
+ ;
+}
--- /dev/null
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+ char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+omp_depend_t bar (void);
+extern const omp_depend_t cdepobj;
+extern omp_depend_t depobj;
+extern omp_depend_t depobja[4];
+extern omp_depend_t *pdepobj;
+int a, b, i, j;
+
+void
+f1 (void)
+{
+ #pragma omp depobj(depobj) depend(in : a)
+ #pragma omp depobj(depobj) update(inout)
+ #pragma omp task depend (depobj)
+ ;
+ #pragma omp depobj(depobj) destroy
+ #pragma omp task depend (iterator (i=1:3) : *(depobja + i))
+ ;
+ #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
+ #pragma omp depobj(*pdepobj) destroy
+}
+
+void
+f2 (void)
+{
+ omp_depend_t depobjb[4];
+ #pragma omp depobj /* { dg-error "expected" } */
+ #pragma omp depobj destroy /* { dg-error "expected" } */
+ #pragma omp depobj (depobj) /* { dg-error "expected 'depend', 'destroy' or 'update' clause" } */
+ #pragma omp depobj (depobj) foobar /* { dg-error "expected 'depend', 'destroy' or 'update' clause" } */
+ #pragma omp depobj(bar ()) update(inout) /* { dg-error "'depobj' expression is not lvalue expression" } */
+ #pragma omp depobj (cdepobj) update(in) /* { dg-error "'const' qualified 'depobj' expression" } */
+ #pragma omp depobj (depobjb) depend(in: a) /* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
+ #pragma omp depobj (pdepobj) depend(in: a) /* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
+ #pragma omp depobj (a) destroy /* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
+ #pragma omp depobj (depobj) depend(a) /* { dg-error "does not have 'omp_depend_t' type in 'depend' clause without dependence type" } */
+ #pragma omp depobj (depobj) update(foobar) /* { dg-error "expected 'in', 'out', 'inout' or 'mutexinoutset'" } */
+ #pragma omp depobj (depobj) depend(in: *depobja) /* { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" } */
+ #pragma omp depobj (depobj) depend(in: a) depend(in: b) /* { dg-error "expected" } */
+ #pragma omp depobj (depobj) depend(in: a) update(out) /* { dg-error "expected" } */
+ #pragma omp depobj (depobj) depend(in: a, b) /* { dg-error "more than one locator in 'depend' clause on 'depobj' construct" } */
+ #pragma omp depobj (depobj) depend(source) /* { dg-error "'depend\\(source\\)' is only allowed in 'omp ordered'" } */
+ #pragma omp depobj (depobj) depend(sink: i + 1, j - 1) /* { dg-error "'depend\\(sink\\)' is only allowed in 'omp ordered'" } */
+ #pragma omp depobj (depobj) depend(iterator (i = 0:2) : in : a) /* { dg-error "'iterator' modifier may not be specified on 'depobj' construct" } */
+ if (0)
+ #pragma omp depobj (depobj) destroy /* { dg-error "'#pragma omp depobj' may only be used in compound statements" } */
+ ;
+}
+
+void
+f3 (void)
+{
+ #pragma omp task depend (depobja[1:2]) /* { dg-error "'depend' clause without dependence type on array section" } */
+ ;
+ #pragma omp task depend (a) /* { dg-error "'a' does not have 'omp_depend_t' type in 'depend' clause without dependence type" } */
+ ;
+ #pragma omp task depend (in: depobj) /* { dg-error "'depobj' should not have 'omp_depend_t' type in 'depend' clause with dependence type" } */
+ ;
+}
void
f1 ()
{
- #pragma omp task depend (iterator : in : a) // { dg-error "expected" }
+ #pragma omp task depend (iterator : in : a) // { dg-error "expected|invalid depend kind" }
;
#pragma omp task depend (iterator (for = 0 : 2) : in : a) // { dg-error "expected" }
;
;
#pragma omp task depend (iterator (i = N : 10 : 2, 3) : in : a) // { dg-error "expected" }
;
- #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a) // { dg-error "expected ':'|invalid depend kind" }
- ;
- #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a) // { dg-error "invalid depend kind" }
+ #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a) // { dg-error "expected ':'|invalid depend kind|was not declared|expected '\\)' before ':' token" }
;
#pragma omp task depend (iterator (i = N:32) : in : b[i*2:2])
;
;
}
+template <int N>
void
f4 ()
+{
+ #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a) // { dg-error "invalid depend kind|was not declared|expected '\\)' before ':' token" }
+ ;
+}
+
+void
+f5 ()
{
f1 <struct S, float, int, 0> ();
f2 <int, 1> ();
f3 <struct S, float, int, 0, const int, const long long unsigned> ();
+ f4 <0> ();
}
--- /dev/null
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+ char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+omp_depend_t bar (void);
+extern const omp_depend_t cdepobj;
+extern omp_depend_t depobj, depobj4;
+extern omp_depend_t depobja[4];
+extern omp_depend_t *pdepobj;
+int a, b, i, j;
+
+template <int N>
+void
+f1 (bool x)
+{
+ #pragma omp depobj(x ? depobj : depobj4) depend(in : x ? a : b)
+ #pragma omp depobj(x ? depobj : depobj4) update(inout)
+ #pragma omp task depend (depobj)
+ ;
+ #pragma omp depobj(depobj) destroy
+ #pragma omp task depend (iterator (i=1:3) : *(depobja + i))
+ ;
+ #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
+ #pragma omp depobj(*pdepobj) destroy
+}
+
+template <typename T, typename T2>
+void
+f2 (T &depobj2, T2 depobj3, T *pdepobj)
+{
+ T depobj1;
+ T depobja[4];
+ #pragma omp depobj(depobj1) depend(in : --a)
+ #pragma omp depobj(depobj1) update(inout)
+ #pragma omp task depend (depobj1)
+ ;
+ #pragma omp depobj(depobj1) destroy
+ #pragma omp depobj(depobj2) depend(in : a)
+ #pragma omp depobj(depobj2) update(inout)
+ #pragma omp task depend (depobj2)
+ ;
+ #pragma omp depobj(depobj2) destroy
+ #pragma omp depobj(depobj3) depend(in : a)
+ #pragma omp depobj(depobj3) update(inout)
+ #pragma omp task depend (depobj3)
+ ;
+ #pragma omp depobj(depobj3) destroy
+ for (int q = 1; q < 3; q++)
+ {
+ #pragma omp depobj(depobja[q]) depend (in:a)
+ }
+ #pragma omp task depend (iterator (i=1:3) : *(depobja + i))
+ ;
+ for (int q = 1; q < 3; q++)
+ {
+ #pragma omp depobj(depobja[q]) destroy
+ }
+ #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
+ #pragma omp depobj(*pdepobj) destroy
+}
+
+void
+f3 (bool x)
+{
+ omp_depend_t depobjx, depobjy;
+ f1 <0> (x);
+ f2 <omp_depend_t, omp_depend_t &> (depobjx, depobjy, pdepobj);
+}
+
+template <int N>
+void
+f4 (void)
+{
+ omp_depend_t depobjb[4];
+ #pragma omp depobj // { dg-error "expected" }
+ #pragma omp depobj destroy // { dg-error "expected" }
+ #pragma omp depobj (depobj) // { dg-error "expected 'depend', 'destroy' or 'update' clause" }
+ #pragma omp depobj (depobj) foobar // { dg-error "expected 'depend', 'destroy' or 'update' clause" }
+ #pragma omp depobj(bar ()) update(inout) // { dg-error "'depobj' expression is not lvalue expression" }
+ #pragma omp depobj (cdepobj) update(in) // { dg-error "'const' qualified 'depobj' expression" }
+ #pragma omp depobj (depobjb) depend(in: a) // { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
+ #pragma omp depobj (pdepobj) depend(in: a) // { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
+ #pragma omp depobj (a) destroy // { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
+ #pragma omp depobj (depobj) depend(a) // { dg-error "does not have 'omp_depend_t' type in 'depend' clause without dependence type" }
+ #pragma omp depobj (depobj) update(foobar) // { dg-error "expected 'in', 'out', 'inout' or 'mutexinoutset'" }
+ #pragma omp depobj (depobj) depend(in: *depobja) // { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
+ #pragma omp depobj (depobj) depend(in: a) depend(in: b) // { dg-error "expected" }
+ #pragma omp depobj (depobj) depend(in: a) update(out) // { dg-error "expected" }
+ #pragma omp depobj (depobj) depend(in: a, b) // { dg-error "more than one locator in 'depend' clause on 'depobj' construct" }
+ #pragma omp depobj (depobj) depend(source) // { dg-error "'depend\\(source\\)' is only allowed in 'omp ordered'" }
+ #pragma omp depobj (depobj) depend(sink: i + 1, j - 1) // { dg-error "'depend\\(sink\\)' is only allowed in 'omp ordered'" }
+ #pragma omp depobj (depobj) depend(iterator (i = 0:2) : in : a) // { dg-error "'iterator' modifier may not be specified on 'depobj' construct" }
+ if (0)
+ #pragma omp depobj (depobj) destroy // { dg-error "'#pragma omp depobj' may only be used in compound statements" }
+ ;
+}
+
+template <int N>
+void
+f5 (void)
+{
+ #pragma omp task depend (depobja[1:2]) // { dg-error "'depend' clause without dependence type on array section" }
+ ;
+ #pragma omp task depend (a) // { dg-error "'a' does not have 'omp_depend_t' type in 'depend' clause without dependence type" }
+ ;
+ #pragma omp task depend (in: depobj) // { dg-error "'depobj' should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
+ ;
+}
+
+void
+f6 (omp_depend_t &x)
+{
+ f4 <0> ();
+ f5 <0> ();
+ #pragma omp depobj (x) depend(in: a)
+ #pragma omp depobj (depobj) depend(in: x) // { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
+}
enum omp_clause_depend_kind
{
+ OMP_CLAUSE_DEPEND_UNSPECIFIED,
OMP_CLAUSE_DEPEND_IN,
OMP_CLAUSE_DEPEND_OUT,
OMP_CLAUSE_DEPEND_INOUT,
pp_string (pp, "depend(");
switch (OMP_CLAUSE_DEPEND_KIND (clause))
{
+ case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+ name = NULL;
+ break;
case OMP_CLAUSE_DEPEND_IN:
name = "in";
break;
pp_colon (pp);
t = TREE_VALUE (t);
}
- pp_string (pp, name);
- pp_colon (pp);
+ if (name)
+ {
+ pp_string (pp, name);
+ pp_colon (pp);
+ }
dump_generic_node (pp, t, spc, flags, false);
pp_right_paren (pp);
}
--- /dev/null
+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * gomp-constants.h (GOMP_DEPEND_IN, GOMP_DEPEND_OUT,
+ GOMP_DEPEND_INOUT, GOMP_DEPEND_MUTEXINOUTSET): Define.
+\f
+Copyright (C) 2018 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
at most and shifted by this many bits. */
#define GOMP_TARGET_ARG_VALUE_SHIFT 16
+/* Dependence types in omp_depend_t objects. */
+#define GOMP_DEPEND_IN 1
+#define GOMP_DEPEND_OUT 2
+#define GOMP_DEPEND_INOUT 3
+#define GOMP_DEPEND_MUTEXINOUTSET 4
+
/* HSA specific data structures. */
/* Identifiers of device-specific target arguments. */
+2018-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * omp.h.in (omp_depend_t): New typedef.
+ * task.c (gomp_task_handle_depend): Handle new depend array format
+ in addition to the old. Handle mutexinoutset kinds the same as
+ inout for now, handle unspecified kinds.
+ (gomp_task_maybe_wait_for_dependencies): Likewise.
+ (gomp_create_target_task): Handle new depend array format count in
+ addition to the old.
+ (GOMP_task): Likewise. Adjust function comment.
+ * testsuite/libgomp.c-c++-common/depend-iterator-2.c: New test.
+ * testsuite/libgomp.c-c++-common/depobj-1.c: New test.
+ * testsuite/libgomp.c++/depend-1.C: New test.
+ * testsuite/libgomp.c++/depobj-1.C: New test.
+
2018-06-19 Jakub Jelinek <jakub@redhat.com>
* libgomp_g.h (GOMP_taskwait_depend): Add prototype.
typedef omp_sync_hint_t omp_lock_hint_t;
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t
+{
+ char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
#ifdef __cplusplus
extern "C" {
# define __GOMP_NOTHROW throw ()
void **depend)
{
size_t ndepend = (uintptr_t) depend[0];
- size_t nout = (uintptr_t) depend[1];
size_t i;
hash_entry_type ent;
+ if (ndepend)
+ {
+ /* depend[0] is total # */
+ size_t nout = (uintptr_t) depend[1]; /* # of out: and inout: */
+ /* ndepend - nout is # of in: */
+ for (i = 0; i < ndepend; i++)
+ {
+ task->depend[i].addr = depend[2 + i];
+ task->depend[i].is_in = i >= nout;
+ }
+ }
+ else
+ {
+ ndepend = (uintptr_t) depend[1]; /* total # */
+ size_t nout = (uintptr_t) depend[2]; /* # of out: and inout: */
+ size_t nmutexinoutset = (uintptr_t) depend[3]; /* # of mutexinoutset: */
+ /* For now we treat mutexinoutset like out, which is compliant, but
+ inefficient. */
+ size_t nin = (uintptr_t) depend[4]; /* # of in: */
+ /* ndepend - nout - nmutexinoutset - nin is # of depobjs */
+ size_t normal = nout + nmutexinoutset + nin;
+ size_t n = 0;
+ for (i = normal; i < ndepend; i++)
+ {
+ void **d = (void **) (uintptr_t) depend[5 + i];
+ switch ((uintptr_t) d[1])
+ {
+ case GOMP_DEPEND_OUT:
+ case GOMP_DEPEND_INOUT:
+ case GOMP_DEPEND_MUTEXINOUTSET:
+ break;
+ case GOMP_DEPEND_IN:
+ continue;
+ default:
+ gomp_fatal ("unknown omp_depend_t dependence type %d",
+ (int) (uintptr_t) d[1]);
+ }
+ task->depend[n].addr = d[0];
+ task->depend[n++].is_in = 0;
+ }
+ for (i = 0; i < normal; i++)
+ {
+ task->depend[n].addr = depend[5 + i];
+ task->depend[n++].is_in = i >= nout + nmutexinoutset;
+ }
+ for (i = normal; i < ndepend; i++)
+ {
+ void **d = (void **) (uintptr_t) depend[5 + i];
+ if ((uintptr_t) d[1] != GOMP_DEPEND_IN)
+ continue;
+ task->depend[n].addr = d[0];
+ task->depend[n++].is_in = 1;
+ }
+ }
task->depend_count = ndepend;
task->num_dependees = 0;
if (parent->depend_hash == NULL)
parent->depend_hash = htab_create (2 * ndepend > 12 ? 2 * ndepend : 12);
for (i = 0; i < ndepend; i++)
{
- task->depend[i].addr = depend[2 + i];
task->depend[i].next = NULL;
task->depend[i].prev = NULL;
task->depend[i].task = task;
- task->depend[i].is_in = i >= nout;
task->depend[i].redundant = false;
task->depend[i].redundant_out = false;
last = ent;
/* depend(in:...) doesn't depend on earlier depend(in:...). */
- if (i >= nout && ent->is_in)
+ if (task->depend[i].is_in && ent->is_in)
continue;
if (!ent->is_in)
then the task may be executed by any member of the team.
DEPEND is an array containing:
+ if depend[0] is non-zero, then:
depend[0]: number of depend elements.
- depend[1]: number of depend elements of type "out".
- depend[2..N+1]: address of [1..N]th depend element. */
+ depend[1]: number of depend elements of type "out/inout".
+ depend[2..N+1]: address of [1..N]th depend element.
+ otherwise, when depend[0] is zero, then:
+ depend[1]: number of depend elements.
+ depend[2]: number of depend elements of type "out/inout".
+ depend[3]: number of depend elements of type "mutexinoutset".
+ depend[4]: number of depend elements of type "in".
+ depend[5..4+depend[2]+depend[3]+depend[4]]: address of depend elements
+ depend[5+depend[2]+depend[3]+depend[4]..4+depend[1]]: address of
+ omp_depend_t objects. */
void
GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
size_t depend_size = 0;
if (flags & GOMP_TASK_FLAG_DEPEND)
- depend_size = ((uintptr_t) depend[0]
+ depend_size = ((uintptr_t) (depend[0] ? depend[0] : depend[1])
* sizeof (struct gomp_task_depend_entry));
task = gomp_malloc (sizeof (*task) + depend_size
+ arg_size + arg_align - 1);
if (depend != NULL)
{
- depend_cnt = (uintptr_t) depend[0];
+ depend_cnt = (uintptr_t) (depend[0] ? depend[0] : depend[1]);
depend_size = depend_cnt * sizeof (struct gomp_task_depend_entry);
}
if (fn)
struct gomp_team *team = thr->ts.team;
struct gomp_task_depend_entry elem, *ent = NULL;
struct gomp_taskwait taskwait;
- size_t ndepend = (uintptr_t) depend[0];
+ size_t orig_ndepend = (uintptr_t) depend[0];
size_t nout = (uintptr_t) depend[1];
+ size_t ndepend = orig_ndepend;
+ size_t normal = ndepend;
+ size_t n = 2;
size_t i;
size_t num_awaited = 0;
struct gomp_task *child_task = NULL;
struct gomp_task *to_free = NULL;
int do_wake = 0;
+ if (ndepend == 0)
+ {
+ ndepend = nout;
+ nout = (uintptr_t) depend[2] + (uintptr_t) depend[3];
+ normal = nout + (uintptr_t) depend[4];
+ n = 5;
+ }
gomp_mutex_lock (&team->task_lock);
for (i = 0; i < ndepend; i++)
{
- elem.addr = depend[i + 2];
+ elem.addr = depend[i + n];
+ elem.is_in = i >= nout;
+ if (__builtin_expect (i >= normal, 0))
+ {
+ void **d = (void **) elem.addr;
+ switch ((uintptr_t) d[1])
+ {
+ case GOMP_DEPEND_IN:
+ break;
+ case GOMP_DEPEND_OUT:
+ case GOMP_DEPEND_INOUT:
+ case GOMP_DEPEND_MUTEXINOUTSET:
+ elem.is_in = 0;
+ break;
+ default:
+ gomp_fatal ("unknown omp_depend_t dependence type %d",
+ (int) (uintptr_t) d[1]);
+ }
+ elem.addr = d[0];
+ }
ent = htab_find (task->depend_hash, &elem);
for (; ent; ent = ent->next)
- if (i >= nout && ent->is_in)
+ if (elem.is_in && ent->is_in)
continue;
else
{
--- /dev/null
+extern "C" void abort ();
+int a, b, c, d, e;
+
+void
+foo (int &x, bool y)
+{
+ #pragma omp task depend (out: x)
+ a = 1;
+ #pragma omp task depend (out: y ? b : c)
+ (y ? b : c) = 2;
+ #pragma omp task depend (inout: --d)
+ d += 4;
+ #pragma omp task depend (in : a, (y ? b : c), d)
+ e = a + b * 10 + c * 100 + d * 1000;
+}
+
+int
+main ()
+{
+ #pragma omp parallel
+ #pragma omp single
+ foo (a, true);
+ if (e != 1 + 20 + 0 + 3000)
+ abort ();
+ a = b = c = d = e = 0;
+ #pragma omp parallel
+ #pragma omp single
+ foo (a, false);
+ if (e != 1 + 0 + 200 + 3000)
+ abort ();
+}
--- /dev/null
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (omp_depend_t &d1, omp_depend_t *d2)
+{
+ int x = 1;
+ #pragma omp depobj (d1) depend(in: x)
+ #pragma omp depobj (*d2) depend(in: x)
+
+ #pragma omp depobj (d2[0]) update(out)
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(*d2)
+ x = 2;
+ #pragma omp task shared (x) depend(d1)
+ if (x != 2)
+ abort ();
+ }
+ #pragma omp depobj (d2[0]) destroy
+ #pragma omp depobj (d1) destroy
+}
+
+template <typename T>
+void
+dep2 (T &d2)
+{
+ T d1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp depobj (d1) depend(out: x)
+ #pragma omp depobj (*&d2) depend (in:x)
+ #pragma omp depobj(d2)update(in)
+ #pragma omp task shared (x) depend(d1)
+ x = 2;
+ #pragma omp task shared (x) depend(d2)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ #pragma omp depobj(d1)destroy
+ #pragma omp depobj((&d2)[0]) destroy
+ }
+}
+
+template <typename T>
+void
+dep3 (void)
+{
+ T d[2];
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp depobj(d[0]) depend(out:x)
+ #pragma omp depobj(d[1]) depend(in: x)
+ #pragma omp task shared (x) depend(*d)
+ x = 2;
+ #pragma omp task shared (x) depend(*(d + 1))
+ if (x != 2)
+ abort ();
+ }
+ }
+ #pragma omp depobj(d[0]) destroy
+ #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+template <int N>
+void
+antidep (void)
+{
+ xx = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared(xx) depend(dd2)
+ if (xx != 1)
+ abort ();
+ #pragma omp task shared(xx) depend(dd1)
+ xx = 2;
+ }
+}
+
+int
+main ()
+{
+ omp_depend_t d1, d2, d3;
+ dep (d1, &d2);
+ dep2 <omp_depend_t> (d3);
+ dep3 <omp_depend_t> ();
+ #pragma omp depobj (dd1) depend (inout: xx)
+ #pragma omp depobj (dd2) depend (in : xx)
+ antidep <0> ();
+ #pragma omp depobj (dd2) destroy
+ #pragma omp depobj (dd1) destroy
+ return 0;
+}
--- /dev/null
+volatile int v;
+
+__attribute__((noipa)) void
+foo (int *p, int i)
+{
+ #pragma omp task depend (out: p[0])
+ v++;
+ #pragma omp task depend (in: p[0])
+ v++;
+ #pragma omp task depend (inout: p[0])
+ v++;
+ #pragma omp task depend (mutexinoutset: p[0])
+ v++;
+ #pragma omp task depend (out: p[0]) depend (in: p[1])
+ v++;
+ #pragma omp task depend (in: p[0]) depend (inout: p[1])
+ v++;
+ #pragma omp task depend (inout: p[0]) depend (mutexinoutset: p[1])
+ v++;
+ #pragma omp task depend (mutexinoutset: p[0]) depend (out: p[1])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : out : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : in : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : inout : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : mutexinoutset : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : out : p[j]) depend (iterator (j=0:2) : in : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : in : p[j]) depend (iterator (j=0:2) : inout : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : inout : p[j]) depend (iterator (j=0:2) : mutexinoutset : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) : mutexinoutset : p[j]) depend (iterator (j=0:2) : out : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : out : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : in : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : inout : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : mutexinoutset : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : out : p[j]) depend (iterator (j=0:i) : in : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : in : p[j]) depend (iterator (j=0:i) : inout : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : inout : p[j]) depend (iterator (j=0:i) : mutexinoutset : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) : mutexinoutset : p[j]) depend (iterator (j=0:i) : out : p[j + 2])
+ v++;
+}
+
+int
+main ()
+{
+ int p[4];
+ foo (p, 2);
+ foo (p, -1);
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (void)
+{
+ int x = 1;
+ omp_depend_t d1, d2;
+ #pragma omp depobj (d1) depend(in: x)
+ #pragma omp depobj (d2) depend(in: x)
+ #pragma omp depobj (d2) update(out)
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(d2)
+ x = 2;
+ #pragma omp task shared (x) depend(d1)
+ if (x != 2)
+ abort ();
+ }
+ #pragma omp depobj (d2) destroy
+ #pragma omp depobj (d1) destroy
+}
+
+void
+dep2 (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ omp_depend_t d1, d2;
+ #pragma omp depobj (d1) depend(out: x)
+ #pragma omp depobj (*&d2) depend (in:x)
+ #pragma omp depobj(d2)update(in)
+ #pragma omp task shared (x) depend(d1)
+ x = 2;
+ #pragma omp task shared (x) depend(d2)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ #pragma omp depobj(d1)destroy
+ #pragma omp depobj((&d2)[0]) destroy
+ }
+}
+
+void
+dep3 (void)
+{
+ omp_depend_t d[2];
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp depobj(d[0]) depend(out:x)
+ #pragma omp depobj(d[1]) depend(in: x)
+ #pragma omp task shared (x) depend(*d)
+ x = 2;
+ #pragma omp task shared (x) depend(*(d + 1))
+ if (x != 2)
+ abort ();
+ }
+ }
+ #pragma omp depobj(d[0]) destroy
+ #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+void
+antidep (void)
+{
+ xx = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared(xx) depend(dd2)
+ if (xx != 1)
+ abort ();
+ #pragma omp task shared(xx) depend(dd1)
+ xx = 2;
+ }
+}
+
+int
+main ()
+{
+ dep ();
+ dep2 ();
+ dep3 ();
+ #pragma omp depobj (dd1) depend (inout: xx)
+ #pragma omp depobj (dd2) depend (in : xx)
+ antidep ();
+ #pragma omp depobj (dd2) destroy
+ #pragma omp depobj (dd1) destroy
+ return 0;
+}