Hi! The latest spec proposals change the meaning of the ordered(n) clause if collapse > 1 to count the number of source loops. The ordered >= collapse requirement is something I'm pushing for even when it is not in the spec (yet). And, finally, another proposed change is that the + or - signs in the sink: vector are significant (primarily for unsigned iterators).
Tested on x86_64-linux, committed to gomp-4_1-branch. 2015-09-25 Jakub Jelinek <ja...@redhat.com> * tree.h (OMP_CLAUSE_DEPEND_SINK_NEGATIVE): Define. * omp-low.c (extract_omp_for_data, expand_omp_for_init_counts, expand_omp_ordered_source, expand_omp_ordered_sink, expand_omp_for_ordered_loops, expand_omp_for_generic): Adjust for fd->ordered being newly 0 when it used to be 0 before, but otherwise being equal to fd->collapse - 1 + old fd->ordered. expand_omp_ordered_source_sink): Likewise. Warn for lexically later iteration sink, or for sink on iteration never in iteration space. Use OMP_CLAUSE_DEPEND_SINK_NEGATIVE. (lower_depend_clauses): Assert not seeing sink/source depend kinds. * tree-pretty-print.c (dump_omp_clause): Use OMP_CLAUSE_DEPEND_SINK_NEGATIVE for the +/- sign of sink vector constants. gcc/c/ * c-parser.c (c_parser_omp_clause_depend_sink): Put - sign into OMP_CLAUSE_DEPEND_SINK_NEGATIVE instead of negating the number. (c_parser_omp_for_loop): Adjust for ordered clause counting source loops before collapsing instead of after it. Require ordered clause parameter to be >= collapse parameter. gcc/cp/ * parser.c (cp_parser_omp_clause_depend_sink): Put - sign into OMP_CLAUSE_DEPEND_SINK_NEGATIVE instead of negating the number. (cp_parser_omp_for_loop): Adjust for ordered clause counting source loops before collapsing instead of after it. Require ordered clause parameter to be >= collapse parameter. * pt.c (tsubst_omp_clause_decl): Copy OMP_CLAUSE_DEPEND_SINK_NEGATIVE flag. gcc/testsuite/ * c-c++-common/gomp/sink-1.c (foo): Adjust for new meaning of ordered clause on collapse > 1 loops. * gcc.dg/gomp/sink-fold-2.c (funk): Remove xfails and adjust for new diagnostics wording and only warnings, no errors. libgomp/ * testsuite/libgomp.c/doacross-1.c (main): Adjust for new meaning of ordered clause on collapse > 1 loops. --- gcc/tree.h.jj 2015-09-03 16:36:19.000000000 +0200 +++ gcc/tree.h 2015-09-25 13:40:16.739807842 +0200 @@ -1446,6 +1446,9 @@ extern void protected_set_expr_location #define OMP_CLAUSE_DEPEND_KIND(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind) +#define OMP_CLAUSE_DEPEND_SINK_NEGATIVE(NODE) \ + TREE_PUBLIC (TREE_LIST_CHECK (NODE)) + #define OMP_CLAUSE_MAP_KIND(NODE) \ ((enum gomp_map_kind) OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind) #define OMP_CLAUSE_SET_MAP_KIND(NODE, MAP_KIND) \ --- gcc/omp-low.c.jj 2015-09-24 20:20:32.000000000 +0200 +++ gcc/omp-low.c 2015-09-25 18:17:13.331812912 +0200 @@ -565,7 +565,7 @@ extract_omp_for_data (gomp_for *for_stmt ? integer_zero_node : integer_one_node; } - int cnt = fd->collapse + (fd->ordered > 0 ? fd->ordered - 1 : 0); + int cnt = fd->ordered ? fd->ordered : fd->collapse; for (i = 0; i < cnt; i++) { if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL)) @@ -6761,7 +6761,7 @@ expand_omp_for_init_counts (struct omp_f return; } - for (i = fd->collapse; i < fd->collapse + fd->ordered - 1; i++) + for (i = fd->collapse; i < fd->ordered; i++) { tree itype = TREE_TYPE (fd->loops[i].v); counts[i] = NULL_TREE; @@ -6770,12 +6770,12 @@ expand_omp_for_init_counts (struct omp_f fold_convert (itype, fd->loops[i].n2)); if (t && integer_zerop (t)) { - for (i = fd->collapse; i < fd->collapse + fd->ordered - 1; i++) + for (i = fd->collapse; i < fd->ordered; i++) counts[i] = build_int_cst (type, 0); break; } } - for (i = 0; i < fd->collapse + (fd->ordered ? fd->ordered - 1 : 0); i++) + for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++) { tree itype = TREE_TYPE (fd->loops[i].v); @@ -7074,8 +7074,7 @@ expand_omp_ordered_source (gimple_stmt_i enum built_in_function source_ix = BUILT_IN_GOMP_DOACROSS_POST; gimple g = gimple_build_call (builtin_decl_explicit (source_ix), 1, - build_fold_addr_expr (counts[fd->collapse - + fd->ordered - 1])); + build_fold_addr_expr (counts[fd->ordered])); gimple_set_location (g, loc); gsi_insert_before (gsi, g, GSI_SAME_STMT); } @@ -7091,13 +7090,38 @@ expand_omp_ordered_sink (gimple_stmt_ite tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE; int i; gimple_stmt_iterator gsi2 = *gsi; + bool warned_step = false; + for (i = 0; i < fd->ordered; i++) + { + off = TREE_PURPOSE (deps); + if (!integer_zerop (off)) + { + gcc_assert (fd->loops[i].cond_code == LT_EXPR + || fd->loops[i].cond_code == GT_EXPR); + bool forward = fd->loops[i].cond_code == LT_EXPR; + if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + warning_at (loc, 0, "%<depend(sink)%> clause waiting for " + "lexically later iteration"); + break; + } + deps = TREE_CHAIN (deps); + } + /* If all offsets corresponding to the collapsed loops are zero, + this depend clause can be ignored. FIXME: but there is still a + flush needed. We need to emit one __sync_synchronize () for it + though (perhaps conditionally)? Solve this together with the + conservative dependence folding optimization. + if (i >= fd->collapse) + return; */ + + deps = OMP_CLAUSE_DECL (c); gsi_prev (&gsi2); edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2)); edge e2 = split_block_after_labels (e1->dest); *gsi = gsi_after_labels (e1->dest); - for (i = 0; i < fd->collapse + fd->ordered - 1; i++) + for (i = 0; i < fd->ordered; i++) { tree itype = TREE_TYPE (fd->loops[i].v); if (POINTER_TYPE_P (itype)) @@ -7114,51 +7138,34 @@ expand_omp_ordered_sink (gimple_stmt_ite tree a; tree co = fold_convert_loc (loc, itype, off); if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))) - a = fold_build2_loc (loc, POINTER_PLUS_EXPR, - TREE_TYPE (fd->loops[i].v), fd->loops[i].v, - co); + { + if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + co = fold_build1_loc (loc, NEGATE_EXPR, itype, co); + a = fold_build2_loc (loc, POINTER_PLUS_EXPR, + TREE_TYPE (fd->loops[i].v), fd->loops[i].v, + co); + } + else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), + fd->loops[i].v, co); else a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v), fd->loops[i].v, co); - if (!TYPE_UNSIGNED (itype) - || POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))) + if (fd->loops[i].cond_code == LT_EXPR) { - if (fd->loops[i].cond_code == LT_EXPR) - { - if (wi::neg_p (co)) - t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a, - fd->loops[i].n1); - else - t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, - fd->loops[i].n2); - } - else if (wi::neg_p (co)) - t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a, - fd->loops[i].n2); - else - t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a, + if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a, fd->loops[i].n1); + else + t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, + fd->loops[i].n2); } - else if (fd->loops[i].cond_code == LT_EXPR) - { - a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), - a, fd->loops[i].n1); - t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), - fd->loops[i].n2, fd->loops[i].n1); - t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, t); - } + else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a, + fd->loops[i].n2); else - { - a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), - a, fd->loops[i].n2); - a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), - a, - build_int_cst (TREE_TYPE (fd->loops[i].v), - 1)); - t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), - fd->loops[i].n1, fd->loops[i].n2); - t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, t); - } + t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a, + fd->loops[i].n1); } if (cond) cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t); @@ -7172,15 +7179,19 @@ expand_omp_ordered_sink (gimple_stmt_ite : !integer_minus_onep (fd->loops[i].step)) { if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR) - t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, - fold_build1_loc (loc, NEGATE_EXPR, itype, - off), + t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, fold_build1_loc (loc, NEGATE_EXPR, itype, s)); else t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s); t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t, build_int_cst (itype, 0)); + if (integer_zerop (t) && !warned_step) + { + warning_at (loc, 0, "%<depend(sink)%> refers to iteration never " + "in the iteration space"); + warned_step = true; + } cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t); } @@ -7196,13 +7207,13 @@ expand_omp_ordered_sink (gimple_stmt_ite t = fold_convert_loc (loc, fd->iter_type, t); } if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR) - off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, - fold_build1_loc (loc, NEGATE_EXPR, itype, - off), + off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, fold_build1_loc (loc, NEGATE_EXPR, itype, s)); else off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s); + if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + off = fold_build1_loc (loc, NEGATE_EXPR, itype, off); off = fold_convert_loc (loc, fd->iter_type, off); if (i <= fd->collapse - 1 && fd->collapse > 1) { @@ -7251,7 +7262,7 @@ expand_omp_ordered_source_sink (struct o { struct omp_region *inner; int i; - for (i = fd->collapse - 1; i < fd->collapse + fd->ordered - 1; i++) + for (i = fd->collapse - 1; i < fd->ordered; i++) if (i == fd->collapse - 1 && fd->collapse > 1) counts[i] = NULL_TREE; else if (i >= fd->collapse && !cont_bb) @@ -7261,9 +7272,10 @@ expand_omp_ordered_source_sink (struct o counts[i] = NULL_TREE; else counts[i] = create_tmp_var (fd->iter_type, ".orditer"); - tree atype = build_array_type_nelts (fd->iter_type, fd->ordered); - counts[fd->collapse + fd->ordered - 1] = create_tmp_var (atype, ".orditera"); - TREE_ADDRESSABLE (counts[fd->collapse + fd->ordered - 1]) = 1; + tree atype + = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1); + counts[fd->ordered] = create_tmp_var (atype, ".orditera"); + TREE_ADDRESSABLE (counts[fd->ordered]) = 1; for (inner = region->inner; inner; inner = inner->next) if (inner->type == GIMPLE_OMP_ORDERED) @@ -7286,25 +7298,25 @@ expand_omp_ordered_source_sink (struct o } } -/* Wrap the body into fd->ordered - 1 loops that aren't collapsed. */ +/* Wrap the body into fd->ordered - fd->collapse loops that aren't + collapsed. */ static basic_block expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts, basic_block cont_bb, basic_block body_bb) { - if (fd->ordered <= 1) + if (fd->ordered == fd->collapse) return cont_bb; if (!cont_bb) { gimple_stmt_iterator gsi = gsi_after_labels (body_bb); - for (int i = fd->collapse; i < fd->collapse + fd->ordered - 1; i++) + for (int i = fd->collapse; i < fd->ordered; i++) { tree type = TREE_TYPE (fd->loops[i].v); tree n1 = fold_convert (type, fd->loops[i].n1); expand_omp_build_assign (&gsi, fd->loops[i].v, n1); - tree aref = build4 (ARRAY_REF, fd->iter_type, - counts[fd->collapse + fd->ordered - 1], + tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered], size_int (i - fd->collapse + 1), NULL_TREE, NULL_TREE); expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type)); @@ -7312,7 +7324,7 @@ expand_omp_for_ordered_loops (struct omp return NULL; } - for (int i = fd->collapse + fd->ordered - 2; i >= fd->collapse; i--) + for (int i = fd->ordered - 1; i >= fd->collapse; i--) { tree t, type = TREE_TYPE (fd->loops[i].v); gimple_stmt_iterator gsi = gsi_after_labels (body_bb); @@ -7321,8 +7333,7 @@ expand_omp_for_ordered_loops (struct omp if (counts[i]) expand_omp_build_assign (&gsi, counts[i], build_zero_cst (fd->iter_type)); - tree aref = build4 (ARRAY_REF, fd->iter_type, - counts[fd->collapse + fd->ordered - 1], + tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered], size_int (i - fd->collapse + 1), NULL_TREE, NULL_TREE); expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type)); @@ -7358,8 +7369,7 @@ expand_omp_for_ordered_loops (struct omp t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); } - aref = build4 (ARRAY_REF, fd->iter_type, - counts[fd->collapse + fd->ordered - 1], + aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered], size_int (i - fd->collapse + 1), NULL_TREE, NULL_TREE); expand_omp_build_assign (&gsi, aref, t); gsi_prev (&gsi); @@ -7535,8 +7545,7 @@ expand_omp_for_generic (struct omp_regio int first_zero_iter1 = -1, first_zero_iter2 = -1; basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL; - counts = XALLOCAVEC (tree, fd->collapse - + (fd->ordered ? fd->ordered - 1 + 1 : 0)); + counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse); expand_omp_for_init_counts (fd, &gsi, entry_bb, counts, zero_iter1_bb, first_zero_iter1, zero_iter2_bb, first_zero_iter2, l2_dom_bb); @@ -7547,7 +7556,7 @@ expand_omp_for_generic (struct omp_regio some loop has zero iterations. But the body shouldn't be executed in that case, so just avoid uninit warnings. */ for (i = first_zero_iter1; - i < fd->collapse + (fd->ordered ? fd->ordered - 1 : 0); i++) + i < (fd->ordered ? fd->ordered : fd->collapse); i++) if (SSA_VAR_P (counts[i])) TREE_NO_WARNING (counts[i]) = 1; gsi_prev (&gsi); @@ -7564,7 +7573,7 @@ expand_omp_for_generic (struct omp_regio /* Some counts[i] vars might be uninitialized if some loop has zero iterations. But the body shouldn't be executed in that case, so just avoid uninit warnings. */ - for (i = first_zero_iter2; i < fd->collapse + fd->ordered - 1; i++) + for (i = first_zero_iter2; i < fd->ordered; i++) if (SSA_VAR_P (counts[i])) TREE_NO_WARNING (counts[i]) = 1; if (zero_iter1_bb) @@ -7640,18 +7649,20 @@ expand_omp_for_generic (struct omp_regio t3 = build_fold_addr_expr (istart0); if (fd->ordered) { - t0 = build_int_cst (unsigned_type_node, fd->ordered); + t0 = build_int_cst (unsigned_type_node, + fd->ordered - fd->collapse + 1); arr = create_tmp_var (build_array_type_nelts (fd->iter_type, - fd->ordered), + fd->ordered + - fd->collapse + 1), ".omp_counts"); DECL_NAMELESS (arr) = 1; TREE_ADDRESSABLE (arr) = 1; TREE_STATIC (arr) = 1; vec<constructor_elt, va_gc> *v; - vec_alloc (v, fd->ordered); + vec_alloc (v, fd->ordered - fd->collapse + 1); int idx; - for (idx = 0; idx < fd->ordered; idx++) + for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++) { tree c; if (idx == 0 && fd->collapse > 1) @@ -7927,7 +7938,7 @@ expand_omp_for_generic (struct omp_regio those counts only for collapsed loops, and only for the 2nd till the last collapsed one. Move those one element earlier, we'll use counts[fd->collapse - 1] for the first source/sink - iteration counter and so on and counts[fd->collapse + fd->ordered - 1] + iteration counter and so on and counts[fd->ordered] as the array holding the current counter values for depend(source). */ if (fd->collapse > 1) @@ -7944,8 +7955,7 @@ expand_omp_for_generic (struct omp_regio t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1], build_int_cst (fd->iter_type, 1)); expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t); - tree aref = build4 (ARRAY_REF, fd->iter_type, - counts[fd->collapse + fd->ordered - 1], + tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered], size_zero_node, NULL_TREE, NULL_TREE); expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]); t = counts[fd->collapse - 1]; @@ -7959,8 +7969,7 @@ expand_omp_for_generic (struct omp_regio t = fold_convert (fd->iter_type, t); } gsi = gsi_last_bb (l0_bb); - tree aref = build4 (ARRAY_REF, fd->iter_type, - counts[fd->collapse + fd->ordered - 1], + tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered], size_zero_node, NULL_TREE, NULL_TREE); t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false, GSI_CONTINUE_LINKING); @@ -8001,8 +8010,8 @@ expand_omp_for_generic (struct omp_regio t = fold_convert (fd->iter_type, t); } tree aref = build4 (ARRAY_REF, fd->iter_type, - counts[fd->collapse + fd->ordered - 1], - size_zero_node, NULL_TREE, NULL_TREE); + counts[fd->ordered], size_zero_node, + NULL_TREE, NULL_TREE); t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); expand_omp_build_assign (&gsi, aref, t); @@ -8050,7 +8059,7 @@ expand_omp_for_generic (struct omp_regio gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT); if (fd->ordered) { - tree arr = counts[fd->collapse + fd->ordered - 1]; + tree arr = counts[fd->ordered]; tree clobber = build_constructor (TREE_TYPE (arr), NULL); TREE_THIS_VOLATILE (clobber) = 1; gsi_insert_after (&gsi, gimple_build_assign (arr, clobber), @@ -13613,8 +13622,7 @@ lower_depend_clauses (tree *pclauses, gi break; case OMP_CLAUSE_DEPEND_SOURCE: case OMP_CLAUSE_DEPEND_SINK: - /* FIXME: */ - break; + /* FALLTHRU */ default: gcc_unreachable (); } --- gcc/tree-pretty-print.c.jj 2015-09-03 16:35:58.000000000 +0200 +++ gcc/tree-pretty-print.c 2015-09-25 15:04:46.911844111 +0200 @@ -569,7 +569,9 @@ dump_omp_clause (pretty_printer *pp, tre if (TREE_PURPOSE (t) != integer_zero_node) { tree p = TREE_PURPOSE (t); - if (!wi::neg_p (p, TYPE_SIGN (TREE_TYPE (p)))) + if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (t)) + pp_minus (pp); + else pp_plus (pp); dump_generic_node (pp, TREE_PURPOSE (t), spc, flags, false); --- gcc/c/c-parser.c.jj 2015-09-10 10:45:20.000000000 +0200 +++ gcc/c/c-parser.c 2015-09-25 14:47:20.501151011 +0200 @@ -11913,14 +11913,13 @@ c_parser_omp_clause_depend_sink (c_parse c_parser_consume_token (parser); - bool neg; + bool neg = false; if (c_parser_next_token_is (parser, CPP_MINUS)) neg = true; - else if (c_parser_next_token_is (parser, CPP_PLUS)) - neg = false; - else + else if (!c_parser_next_token_is (parser, CPP_PLUS)) { addend = integer_zero_node; + neg = false; goto add_to_vector; } c_parser_consume_token (parser); @@ -11937,21 +11936,15 @@ c_parser_omp_clause_depend_sink (c_parse c_parser_error (parser, "expected integer"); return list; } - if (neg) - { - bool overflow; - wide_int offset = wi::neg (addend, &overflow); - addend = wide_int_to_tree (TREE_TYPE (addend), offset); - if (overflow) - warning_at (c_parser_peek_token (parser)->location, - OPT_Woverflow, - "overflow in implicit constant conversion"); - } c_parser_consume_token (parser); add_to_vector: if (t != error_mark_node) - vec = tree_cons (addend, t, vec); + { + vec = tree_cons (addend, t, vec); + if (neg) + OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + } if (c_parser_next_token_is_not (parser, CPP_COMMA)) break; @@ -13645,6 +13638,7 @@ c_parser_omp_for_loop (location_t loc, c tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; tree declv, condv, incrv, initv, ret = NULL_TREE; tree pre_body = NULL_TREE, this_pre_body; + tree ordered_cl = NULL_TREE; bool fail = false, open_brace_parsed = false; int i, collapse = 1, ordered = 0, count, nbraces = 0; location_t for_loc; @@ -13655,10 +13649,22 @@ c_parser_omp_for_loop (location_t loc, c collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED && OMP_CLAUSE_ORDERED_EXPR (cl)) - ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); + { + ordered_cl = cl; + ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); + } + + if (ordered && ordered < collapse) + { + error_at (OMP_CLAUSE_LOCATION (ordered_cl), + "%<ordered%> clause parameter is less than %<collapse%>"); + OMP_CLAUSE_ORDERED_EXPR (ordered_cl) + = build_int_cst (NULL_TREE, collapse); + ordered = collapse; + } gcc_assert (collapse >= 1 && ordered >= 0); - count = collapse + (ordered > 0 ? ordered - 1 : 0); + count = ordered ? ordered : collapse; declv = make_tree_vec (count); initv = make_tree_vec (count); --- gcc/cp/parser.c.jj 2015-09-10 12:03:29.000000000 +0200 +++ gcc/cp/parser.c 2015-09-25 14:47:29.098025038 +0200 @@ -30464,12 +30464,10 @@ cp_parser_omp_clause_depend_sink (cp_par id_loc); } - bool neg; + bool neg = false; if (cp_lexer_next_token_is (parser->lexer, CPP_MINUS)) neg = true; - else if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)) - neg = false; - else + else if (!cp_lexer_next_token_is (parser->lexer, CPP_PLUS)) { addend = integer_zero_node; goto add_to_vector; @@ -30488,21 +30486,15 @@ cp_parser_omp_clause_depend_sink (cp_par cp_parser_error (parser, "expected integer"); return list; } - if (neg) - { - bool overflow; - wide_int offset = wi::neg (addend, &overflow); - addend = wide_int_to_tree (TREE_TYPE (addend), offset); - if (overflow) - warning_at (cp_lexer_peek_token (parser->lexer)->location, - OPT_Woverflow, - "overflow in implicit constant conversion"); - } cp_lexer_consume_token (parser->lexer); add_to_vector: if (t != error_mark_node) - vec = tree_cons (addend, t, vec); + { + vec = tree_cons (addend, t, vec); + if (neg) + OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + } if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) break; @@ -32212,7 +32204,7 @@ cp_parser_omp_for_loop (cp_parser *parse { tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret; tree real_decl, initv, condv, incrv, declv; - tree this_pre_body, cl; + tree this_pre_body, cl, ordered_cl = NULL_TREE; location_t loc_first; bool collapse_err = false; int i, collapse = 1, ordered = 0, count, nbraces = 0; @@ -32223,10 +32215,22 @@ cp_parser_omp_for_loop (cp_parser *parse collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED && OMP_CLAUSE_ORDERED_EXPR (cl)) - ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); + { + ordered_cl = cl; + ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); + } + + if (ordered && ordered < collapse) + { + error_at (OMP_CLAUSE_LOCATION (ordered_cl), + "%<ordered%> clause parameter is less than %<collapse%>"); + OMP_CLAUSE_ORDERED_EXPR (ordered_cl) + = build_int_cst (NULL_TREE, collapse); + ordered = collapse; + } gcc_assert (collapse >= 1 && ordered >= 0); - count = collapse + (ordered > 0 ? ordered - 1 : 0); + count = ordered ? ordered : collapse; declv = make_tree_vec (count); initv = make_tree_vec (count); --- gcc/cp/pt.c.jj 2015-09-10 10:45:41.000000000 +0200 +++ gcc/cp/pt.c 2015-09-25 14:53:22.986839372 +0200 @@ -14086,7 +14086,10 @@ tsubst_omp_clause_decl (tree decl, tree && TREE_VALUE (decl) == length && TREE_CHAIN (decl) == chain) return decl; - return tree_cons (low_bound, length, chain); + tree ret = tree_cons (low_bound, length, chain); + OMP_CLAUSE_DEPEND_SINK_NEGATIVE (ret) + = OMP_CLAUSE_DEPEND_SINK_NEGATIVE (decl); + return ret; } tree ret = tsubst_expr (decl, args, complain, in_decl, /*integral_constant_expression_p=*/false); --- gcc/testsuite/c-c++-common/gomp/sink-1.c.jj 2015-07-15 13:00:32.000000000 +0200 +++ gcc/testsuite/c-c++-common/gomp/sink-1.c 2015-09-25 16:47:40.294063449 +0200 @@ -68,7 +68,7 @@ void foo (int n, int m, int o) { int i, j, k; - #pragma omp for collapse(2) ordered(2) + #pragma omp for collapse(2) ordered(3) for (i = 0; i < m; i++) { for (j = 0; j < n; j++) --- gcc/testsuite/gcc.dg/gomp/sink-fold-2.c.jj 2015-09-24 19:37:06.000000000 +0200 +++ gcc/testsuite/gcc.dg/gomp/sink-fold-2.c 2015-09-25 18:14:38.626071155 +0200 @@ -11,8 +11,8 @@ funk () for (i=0; i < N; i += 3) for (j=0; j < N; ++j) { -#pragma omp ordered depend(sink:i-8,j-1) /* { dg-warning "ignoring sink clause with offset that is not a multiple" "" { xfail *-*-* } } */ -#pragma omp ordered depend(sink:i+3,j-1) /* { dg-error "first offset must be in opposite direction" "" { xfail *-*-* } } */ +#pragma omp ordered depend(sink:i-8,j-1) /* { dg-warning "refers to iteration never in the iteration space" } */ +#pragma omp ordered depend(sink:i+3,j-1) /* { dg-warning "waiting for lexically later iteration" } */ bar(); #pragma omp ordered depend(source) } --- libgomp/testsuite/libgomp.c/doacross-1.c.jj 2015-09-24 20:20:32.000000000 +0200 +++ libgomp/testsuite/libgomp.c/doacross-1.c 2015-09-25 16:54:47.118834681 +0200 @@ -79,7 +79,7 @@ main () #define D(n) C(n##0) C(n##1) C(n##2) C(n##3) D(m) #undef A - #pragma omp for collapse (2) ordered(60) schedule(dynamic, 15) + #pragma omp for collapse (2) ordered(61) schedule(dynamic, 15) for (i = 0; i < N / 32; i++) for (j = 7; j > 1; j--) for (k = 6; k >= 0; k -= 2) @@ -119,7 +119,7 @@ main () c[i][j][k] = 3; } - #pragma omp for collapse(2) ordered(3) lastprivate (i, j, k) + #pragma omp for collapse(2) ordered(4) lastprivate (i, j, k) for (i = 0; i < d + 1; i++) for (j = d + 1; j >= 0; j--) for (k = 0; k < d; k++) @@ -136,7 +136,7 @@ main () abort (); i = 8; j = 9; k = 10; } - #pragma omp for collapse(2) ordered(3) lastprivate (i, j, k, m) + #pragma omp for collapse(2) ordered(4) lastprivate (i, j, k, m) for (i = 0; i < d + 1; i++) for (j = d + 1; j >= 0; j--) for (k = 0; k < d + 2; k++) @@ -150,7 +150,7 @@ main () #pragma omp single if (i != 1 || j != -1 || k != 2 || m != 0) abort (); - #pragma omp for collapse(2) ordered(3) nowait + #pragma omp for collapse(2) ordered(4) nowait for (i = 0; i < d + 1; i++) for (j = d; j > 0; j--) for (k = 0; k < d + 2; k++) Jakub