+2021-02-09 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ Backport from mainline
+ 2020-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_FOR_NON_RECTANGULAR): Define.
+ * gimplify.c (gimplify_omp_for): Diagnose schedule, ordered
+ or dist_schedule clause on non-rectangular loops. Handle
+ gimplification of non-rectangular lb/b expressions. When changing
+ iteration variable, adjust also non-rectangular lb/b expressions
+ referencing that.
+ * omp-general.h (struct omp_for_data_loop): Add m1, m2 and outer
+ members.
+ (struct omp_for_data): Add non_rect member.
+ * omp-general.c (omp_extract_for_data): Handle non-rectangular
+ loops. Fill in non_rect, m1, m2 and outer.
+ * omp-low.c (lower_omp_for): Handle non-rectangular lb/b expressions.
+ * omp-expand.c (expand_omp_for): Emit sorry_at for unsupported
+ non-rectangular loop cases and assert for cases that can't be
+ non-rectangular.
+ * tree-pretty-print.c (dump_mem_ref): Formatting fix.
+ (dump_omp_loop_non_rect_expr): New function.
+ (dump_generic_node): Handle non-rectangular OpenMP loops.
+ * tree-pretty-print.h (dump_omp_loop_non_rect_expr): Declare.
+ * gimple-pretty-print.c (dump_gimple_omp_for): Handle non-rectangular
+ OpenMP loops.
+
2021-01-22 Kwok Cheung Yeung <kcy@codesourcery.com>
Backport from mainline
+2021-02-09 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ Backport from mainline
+ 2020-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ * c-common.h (c_omp_check_loop_iv_exprs): Add an int argument.
+ * c-omp.c (struct c_omp_check_loop_iv_data): Add maybe_nonrect and
+ idx members.
+ (c_omp_is_loop_iterator): New function.
+ (c_omp_check_loop_iv_r): Use it. Add support for silent scanning
+ if outer loop iterator is present. Perform duplicate checking through
+ hash_set in the function rather than expecting caller to do that.
+ Pass NULL instead of d->ppset to walk_tree_1.
+ (c_omp_check_nonrect_loop_iv): New function.
+ (c_omp_check_loop_iv): Use it. Fill in new members, allow
+ non-rectangular loop forms, diagnose multiple associated loops with
+ the same iterator. Pass NULL instead of &pset to walk_tree_1.
+ (c_omp_check_loop_iv_exprs): Likewise.
+
2021-01-22 Kwok Cheung Yeung <kcy@codesourcery.com>
Backport from mainline
extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
tree, tree, tree, tree, bool);
extern bool c_omp_check_loop_iv (tree, tree, walk_tree_lh);
-extern bool c_omp_check_loop_iv_exprs (location_t, tree, tree, tree, tree,
+extern bool c_omp_check_loop_iv_exprs (location_t, tree, int, tree, tree, tree,
walk_tree_lh);
extern tree c_finish_oacc_wait (location_t, tree, tree);
extern tree c_oacc_split_loop_clauses (tree, tree *, bool);
#include "attribs.h"
#include "gimplify.h"
#include "tree-iterator.h"
+#include "langhooks.h"
+
/* Complete a #pragma oacc wait construct. LOC is the location of
the #pragma. */
{
tree declv;
bool fail;
+ bool maybe_nonrect;
location_t stmt_loc;
location_t expr_loc;
int kind;
+ int idx;
walk_tree_lh lh;
hash_set<tree> *ppset;
};
+/* Return -1 if DECL is not a loop iterator in loop nest D, otherwise
+ return the index of the loop in which it is an iterator.
+ Return TREE_VEC_LENGTH (d->declv) if it is a C++ range for iterator. */
+
+static int
+c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
+{
+ for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
+ if (decl == TREE_VEC_ELT (d->declv, i)
+ || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
+ && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i))))
+ return i;
+ else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
+ && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
+ && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
+ == TREE_VEC)
+ && decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv,
+ i)), 2))
+ return TREE_VEC_LENGTH (d->declv);
+ return -1;
+}
+
/* Helper function called via walk_tree, to diagnose uses
of associated loop IVs inside of lb, b and incr expressions
of OpenMP loops. */
= (struct c_omp_check_loop_iv_data *) data;
if (DECL_P (*tp))
{
- int i;
- for (i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
- if (*tp == TREE_VEC_ELT (d->declv, i)
- || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
- && *tp == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i)))
- || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
- && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
- && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
- == TREE_VEC)
- && *tp == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv,
- i)), 2)))
- {
- location_t loc = d->expr_loc;
- if (loc == UNKNOWN_LOCATION)
- loc = d->stmt_loc;
- switch (d->kind)
- {
- case 0:
- error_at (loc, "initializer expression refers to "
- "iteration variable %qD", *tp);
- break;
- case 1:
- error_at (loc, "condition expression refers to "
- "iteration variable %qD", *tp);
- break;
- case 2:
- error_at (loc, "increment expression refers to "
- "iteration variable %qD", *tp);
- break;
- }
- d->fail = true;
- }
+ int idx = c_omp_is_loop_iterator (*tp, d);
+ if (idx == -1)
+ return NULL_TREE;
+
+ if ((d->kind & 4) && idx < d->idx)
+ {
+ d->maybe_nonrect = true;
+ return NULL_TREE;
+ }
+
+ if (d->ppset->add (*tp))
+ return NULL_TREE;
+
+ location_t loc = d->expr_loc;
+ if (loc == UNKNOWN_LOCATION)
+ loc = d->stmt_loc;
+
+ switch (d->kind & 3)
+ {
+ case 0:
+ error_at (loc, "initializer expression refers to "
+ "iteration variable %qD", *tp);
+ break;
+ case 1:
+ error_at (loc, "condition expression refers to "
+ "iteration variable %qD", *tp);
+ break;
+ case 2:
+ error_at (loc, "increment expression refers to "
+ "iteration variable %qD", *tp);
+ break;
+ }
+ d->fail = true;
}
+ else if (d->ppset->add (*tp))
+ *walk_subtrees = 0;
/* Don't walk dtors added by C++ wrap_cleanups_r. */
else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
&& TRY_CATCH_IS_CLEANUP (*tp))
{
*walk_subtrees = 0;
return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
- d->ppset, d->lh);
+ NULL, d->lh);
}
return NULL_TREE;
}
+/* Check the allowed expressions for non-rectangular loop nest lb and b
+ expressions. Return the outer var decl referenced in the expression. */
+
+static tree
+c_omp_check_nonrect_loop_iv (tree *tp, struct c_omp_check_loop_iv_data *d,
+ walk_tree_lh lh)
+{
+ d->maybe_nonrect = false;
+ if (d->fail)
+ return NULL_TREE;
+
+ hash_set<tree> pset;
+ hash_set<tree> *ppset = d->ppset;
+ d->ppset = &pset;
+
+ tree t = *tp;
+ if (TREE_CODE (t) == TREE_VEC
+ && TREE_VEC_LENGTH (t) == 3
+ && DECL_P (TREE_VEC_ELT (t, 0))
+ && c_omp_is_loop_iterator (TREE_VEC_ELT (t, 0), d) >= 0)
+ {
+ d->kind &= 3;
+ walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
+ walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
+ d->ppset = ppset;
+ return d->fail ? NULL_TREE : TREE_VEC_ELT (t, 0);
+ }
+
+ while (CONVERT_EXPR_P (t))
+ t = TREE_OPERAND (t, 0);
+
+ tree a1 = t, a2 = integer_zero_node;
+ bool neg_a1 = false, neg_a2 = false;
+ switch (TREE_CODE (t))
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ a1 = TREE_OPERAND (t, 0);
+ a2 = TREE_OPERAND (t, 1);
+ while (CONVERT_EXPR_P (a1))
+ a1 = TREE_OPERAND (a1, 0);
+ while (CONVERT_EXPR_P (a2))
+ a2 = TREE_OPERAND (a2, 0);
+ if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
+ {
+ a2 = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == MINUS_EXPR)
+ neg_a2 = true;
+ t = a1;
+ break;
+ }
+ if (DECL_P (a2) && c_omp_is_loop_iterator (a2, d) >= 0)
+ {
+ a1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == MINUS_EXPR)
+ neg_a1 = true;
+ t = a2;
+ a2 = a1;
+ break;
+ }
+ if (TREE_CODE (a1) == MULT_EXPR && TREE_CODE (a2) == MULT_EXPR)
+ {
+ tree o1 = TREE_OPERAND (a1, 0);
+ tree o2 = TREE_OPERAND (a1, 1);
+ while (CONVERT_EXPR_P (o1))
+ o1 = TREE_OPERAND (o1, 0);
+ while (CONVERT_EXPR_P (o2))
+ o2 = TREE_OPERAND (o2, 0);
+ if ((DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
+ || (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0))
+ {
+ a2 = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == MINUS_EXPR)
+ neg_a2 = true;
+ t = a1;
+ break;
+ }
+ }
+ if (TREE_CODE (a2) == MULT_EXPR)
+ {
+ a1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == MINUS_EXPR)
+ neg_a1 = true;
+ t = a2;
+ a2 = a1;
+ break;
+ }
+ if (TREE_CODE (a1) == MULT_EXPR)
+ {
+ a2 = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == MINUS_EXPR)
+ neg_a2 = true;
+ t = a1;
+ break;
+ }
+ a2 = integer_zero_node;
+ break;
+ default:
+ break;
+ }
+
+ a1 = integer_one_node;
+ if (TREE_CODE (t) == MULT_EXPR)
+ {
+ tree o1 = TREE_OPERAND (t, 0);
+ tree o2 = TREE_OPERAND (t, 1);
+ while (CONVERT_EXPR_P (o1))
+ o1 = TREE_OPERAND (o1, 0);
+ while (CONVERT_EXPR_P (o2))
+ o2 = TREE_OPERAND (o2, 0);
+ if (DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
+ {
+ a1 = TREE_OPERAND (t, 1);
+ t = o1;
+ }
+ else if (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0)
+ {
+ a1 = TREE_OPERAND (t, 0);
+ t = o2;
+ }
+ }
+
+ d->kind &= 3;
+ tree ret = NULL_TREE;
+ if (DECL_P (t) && c_omp_is_loop_iterator (t, d) >= 0)
+ {
+ location_t loc = d->expr_loc;
+ if (loc == UNKNOWN_LOCATION)
+ loc = d->stmt_loc;
+ if (!lang_hooks.types_compatible_p (TREE_TYPE (*tp), TREE_TYPE (t)))
+ {
+ if (d->kind == 0)
+ error_at (loc, "outer iteration variable %qD used in initializer"
+ " expression has type other than %qT",
+ t, TREE_TYPE (*tp));
+ else
+ error_at (loc, "outer iteration variable %qD used in condition"
+ " expression has type other than %qT",
+ t, TREE_TYPE (*tp));
+ d->fail = true;
+ }
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (a1)))
+ {
+ error_at (loc, "outer iteration variable %qD multiplier expression"
+ " %qE is not integral", t, a1);
+ d->fail = true;
+ }
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (a2)))
+ {
+ error_at (loc, "outer iteration variable %qD addend expression"
+ " %qE is not integral", t, a2);
+ d->fail = true;
+ }
+ else
+ {
+ walk_tree_1 (&a1, c_omp_check_loop_iv_r, d, NULL, lh);
+ walk_tree_1 (&a2, c_omp_check_loop_iv_r, d, NULL, lh);
+ }
+ if (!d->fail)
+ {
+ a1 = fold_convert (TREE_TYPE (*tp), a1);
+ a2 = fold_convert (TREE_TYPE (*tp), a2);
+ if (neg_a1)
+ a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
+ if (neg_a2)
+ a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
+ ret = t;
+ *tp = make_tree_vec (3);
+ TREE_VEC_ELT (*tp, 0) = t;
+ TREE_VEC_ELT (*tp, 1) = a1;
+ TREE_VEC_ELT (*tp, 2) = a2;
+ }
+ }
+ else
+ walk_tree_1 (&t, c_omp_check_loop_iv_r, d, NULL, lh);
+
+ d->ppset = ppset;
+ return ret;
+}
+
/* Diagnose invalid references to loop iterators in lb, b and incr
expressions. */
data.declv = declv;
data.fail = false;
+ data.maybe_nonrect = false;
data.stmt_loc = EXPR_LOCATION (stmt);
data.lh = lh;
data.ppset = &pset;
gcc_assert (TREE_OPERAND (cond, 0) == decl);
tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
- data.kind = 0;
+ tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
+ int kind = 0;
+ if (i > 0
+ && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
+ {
+ location_t loc = data.expr_loc;
+ if (loc == UNKNOWN_LOCATION)
+ loc = data.stmt_loc;
+ error_at (loc, "the same loop iteration variables %qD used in "
+ "multiple associated loops", decl);
+ data.fail = true;
+ }
+ /* Handle non-rectangular loop nests. */
+ if (TREE_CODE (stmt) != OACC_LOOP
+ && (TREE_CODE (TREE_OPERAND (init, 1)) == TREE_VEC
+ || INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (init, 1))))
+ && i > 0)
+ kind = 4;
+ data.kind = kind;
+ data.idx = i;
walk_tree_1 (&TREE_OPERAND (init, 1),
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
+ if (data.maybe_nonrect)
+ vec_outer1 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (init, 1),
+ &data, lh);
/* Don't warn for C++ random access iterators here, the
expression then involves the subtraction and always refers
to the original value. The C++ FE needs to warn on those
&& decl == TREE_PURPOSE (TREE_VEC_ELT (declv, i))))
{
data.expr_loc = EXPR_LOCATION (cond);
- data.kind = 1;
+ data.kind = kind | 1;
walk_tree_1 (&TREE_OPERAND (cond, 1),
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
+ if (data.maybe_nonrect)
+ vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
+ &data, lh);
+ }
+ if (vec_outer1 && vec_outer2 && vec_outer1 != vec_outer2)
+ {
+ location_t loc = data.expr_loc;
+ if (loc == UNKNOWN_LOCATION)
+ loc = data.stmt_loc;
+ error_at (loc, "two different outer iteration variables %qD and %qD"
+ " used in a single loop", vec_outer1, vec_outer2);
+ data.fail = true;
}
+ if (vec_outer1 || vec_outer2)
+ OMP_FOR_NON_RECTANGULAR (stmt) = 1;
if (TREE_CODE (incr) == MODIFY_EXPR)
{
gcc_assert (TREE_OPERAND (incr, 0) == decl);
{
data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
walk_tree_1 (&TREE_OPERAND (incr, 0),
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
}
else
{
data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
walk_tree_1 (&TREE_OPERAND (incr, 1),
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
}
}
}
/* Similar, but allows to check the init or cond expressions individually. */
bool
-c_omp_check_loop_iv_exprs (location_t stmt_loc, tree declv, tree decl,
+c_omp_check_loop_iv_exprs (location_t stmt_loc, tree declv, int i, tree decl,
tree init, tree cond, walk_tree_lh lh)
{
hash_set<tree> pset;
data.declv = declv;
data.fail = false;
+ data.maybe_nonrect = false;
data.stmt_loc = stmt_loc;
data.lh = lh;
data.ppset = &pset;
+ data.idx = i;
+ if (i > 0
+ && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
+ {
+ error_at (stmt_loc, "the same loop iteration variables %qD used in "
+ "multiple associated loops", decl);
+ data.fail = true;
+ }
if (init)
{
data.expr_loc = EXPR_LOCATION (init);
data.kind = 0;
walk_tree_1 (&init,
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
}
if (cond)
{
data.kind = 1;
if (TREE_OPERAND (cond, 0) == decl)
walk_tree_1 (&TREE_OPERAND (cond, 1),
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
else
walk_tree_1 (&TREE_OPERAND (cond, 0),
- c_omp_check_loop_iv_r, &data, &pset, lh);
+ c_omp_check_loop_iv_r, &data, NULL, lh);
}
return !data.fail;
}
+2021-02-09 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ Backport from mainline
+ 2020-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_expr_no_commas): Save, clear and restore
+ c_in_omp_for.
+ (c_parser_omp_for_loop): Set c_in_omp_for around some calls to avoid
+ premature c_fully_fold. Defer explicit c_fully_fold calls to after
+ c_finish_omp_for.
+ * c-tree.h (c_in_omp_for): Declare.
+ * c-typeck.c (c_in_omp_for): Define.
+ (build_modify_expr): Avoid c_fully_fold if c_in_omp_for.
+ (digest_init): Likewise.
+ (build_binary_op): Likewise.
+
2021-01-22 Kwok Cheung Yeung <kcy@codesourcery.com>
Backport from mainline
struct c_expr lhs, rhs, ret;
enum tree_code code;
location_t op_location, exp_location;
+ bool save_in_omp_for = c_in_omp_for;
+ c_in_omp_for = false;
gcc_assert (!after || c_dialect_objc ());
lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
op_location = c_parser_peek_token (parser)->location;
code = BIT_IOR_EXPR;
break;
default:
+ c_in_omp_for = save_in_omp_for;
return lhs;
}
c_parser_consume_token (parser);
ret.original_code = ERROR_MARK;
}
ret.original_type = NULL;
+ c_in_omp_for = save_in_omp_for;
return ret;
}
if (i > 0)
vec_safe_push (for_block, c_begin_compound_stmt (true));
this_pre_body = push_stmt_list ();
+ c_in_omp_for = true;
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
NULL, vNULL);
+ c_in_omp_for = false;
if (this_pre_body)
{
this_pre_body = pop_stmt_list (this_pre_body);
init_exp = c_parser_expr_no_commas (parser, NULL);
init_exp = default_function_array_read_conversion (init_loc,
init_exp);
+ c_in_omp_for = true;
init = build_modify_expr (init_loc, decl, decl_exp.original_type,
NOP_EXPR, init_loc, init_exp.value,
init_exp.original_type);
+ c_in_omp_for = false;
init = c_process_expr_stmt (init_loc, init);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
{
location_t cond_loc = c_parser_peek_token (parser)->location;
+ c_in_omp_for = true;
struct c_expr cond_expr
= c_parser_binary_expression (parser, NULL, NULL_TREE);
+ c_in_omp_for = false;
cond = cond_expr.value;
cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
- if (COMPARISON_CLASS_P (cond))
- {
- tree op0 = TREE_OPERAND (cond, 0), op1 = TREE_OPERAND (cond, 1);
- op0 = c_fully_fold (op0, false, NULL);
- op1 = c_fully_fold (op1, false, NULL);
- TREE_OPERAND (cond, 0) = op0;
- TREE_OPERAND (cond, 1) = op1;
- }
switch (cond_expr.original_code)
{
case GT_EXPR:
an error from the initialization parsing. */
if (!fail)
{
+ c_in_omp_for = true;
stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv,
incrv, body, pre_body, true);
+ c_in_omp_for = false;
/* Check for iterators appearing in lb, b or incr expressions. */
if (stmt && !c_omp_check_loop_iv (stmt, declv, NULL))
{
add_stmt (stmt);
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
+ {
+ tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ tree decl = TREE_OPERAND (init, 0);
+ tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
+ gcc_assert (COMPARISON_CLASS_P (cond));
+ gcc_assert (TREE_OPERAND (cond, 0) == decl);
+
+ tree op0 = TREE_OPERAND (init, 1);
+ if (!OMP_FOR_NON_RECTANGULAR (stmt)
+ || TREE_CODE (op0) != TREE_VEC)
+ TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
+ else
+ {
+ TREE_VEC_ELT (op0, 1)
+ = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
+ TREE_VEC_ELT (op0, 2)
+ = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
+ }
+
+ tree op1 = TREE_OPERAND (cond, 1);
+ if (!OMP_FOR_NON_RECTANGULAR (stmt)
+ || TREE_CODE (op1) != TREE_VEC)
+ TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
+ else
+ {
+ TREE_VEC_ELT (op1, 1)
+ = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
+ TREE_VEC_ELT (op1, 2)
+ = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
+ }
+ }
+
if (cclauses != NULL
&& cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
{
extern int in_alignof;
extern int in_sizeof;
extern int in_typeof;
+extern bool c_in_omp_for;
extern tree c_last_sizeof_arg;
extern location_t c_last_sizeof_loc;
/* The level of nesting inside "typeof". */
int in_typeof;
+/* True when parsing OpenMP loop expressions. */
+bool c_in_omp_for;
+
/* The argument of last parsed sizeof expression, only to be tested
if expr.original_code == SIZEOF_EXPR. */
tree c_last_sizeof_arg;
if (!(is_atomic_op && modifycode != NOP_EXPR))
{
tree rhs_semantic_type = NULL_TREE;
- if (TREE_CODE (newrhs) == EXCESS_PRECISION_EXPR)
+ if (!c_in_omp_for)
{
- rhs_semantic_type = TREE_TYPE (newrhs);
- newrhs = TREE_OPERAND (newrhs, 0);
+ if (TREE_CODE (newrhs) == EXCESS_PRECISION_EXPR)
+ {
+ rhs_semantic_type = TREE_TYPE (newrhs);
+ newrhs = TREE_OPERAND (newrhs, 0);
+ }
+ npc = null_pointer_constant_p (newrhs);
+ newrhs = c_fully_fold (newrhs, false, NULL);
+ if (rhs_semantic_type)
+ newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
}
- npc = null_pointer_constant_p (newrhs);
- newrhs = c_fully_fold (newrhs, false, NULL);
- if (rhs_semantic_type)
- newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
+ else
+ npc = null_pointer_constant_p (newrhs);
newrhs = convert_for_assignment (location, rhs_loc, lhstype, newrhs,
rhs_origtype, ic_assign, npc,
NULL_TREE, NULL_TREE, 0);
STRIP_TYPE_NOPS (inside_init);
- if (TREE_CODE (inside_init) == EXCESS_PRECISION_EXPR)
+ if (!c_in_omp_for)
{
- semantic_type = TREE_TYPE (inside_init);
- inside_init = TREE_OPERAND (inside_init, 0);
+ if (TREE_CODE (inside_init) == EXCESS_PRECISION_EXPR)
+ {
+ semantic_type = TREE_TYPE (inside_init);
+ inside_init = TREE_OPERAND (inside_init, 0);
+ }
+ inside_init = c_fully_fold (inside_init, require_constant, &maybe_const);
}
- inside_init = c_fully_fold (inside_init, require_constant, &maybe_const);
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
converted = 1;
resultcode = xresultcode;
- if (c_inhibit_evaluation_warnings == 0)
+ if (c_inhibit_evaluation_warnings == 0 && !c_in_omp_for)
{
bool op0_maybe_const = true;
bool op1_maybe_const = true;
+2021-02-09 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ Backport from mainline
+ 2020-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (handle_omp_for_class_iterator): Adjust
+ c_omp_check_loop_iv_exprs caller.
+ (finish_omp_for): Likewise. Don't call fold_build_cleanup_point_expr
+ before calling c_finish_omp_for and c_omp_check_loop_iv, move it
+ after those calls.
+ * pt.c (tsubst_omp_for_iterator): Handle non-rectangular loops.
+
2021-01-22 Kwok Cheung Yeung <kcy@codesourcery.com>
Backport from mainline
else
decl = RECUR (decl);
}
- init = RECUR (init);
+ if (init && TREE_CODE (init) == TREE_VEC)
+ {
+ init = copy_node (init);
+ TREE_VEC_ELT (init, 0)
+ = tsubst_decl (TREE_VEC_ELT (init, 0), args, complain);
+ TREE_VEC_ELT (init, 1) = RECUR (TREE_VEC_ELT (init, 1));
+ TREE_VEC_ELT (init, 2) = RECUR (TREE_VEC_ELT (init, 2));
+ }
+ else
+ init = RECUR (init);
if (orig_declv && OMP_FOR_ORIG_DECLS (t))
{
if (!range_for)
{
- cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
+ cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
+ if (COMPARISON_CLASS_P (cond)
+ && TREE_CODE (TREE_OPERAND (cond, 1)) == TREE_VEC)
+ {
+ tree lhs = RECUR (TREE_OPERAND (cond, 0));
+ tree rhs = copy_node (TREE_OPERAND (cond, 1));
+ TREE_VEC_ELT (rhs, 0)
+ = tsubst_decl (TREE_VEC_ELT (rhs, 0), args, complain);
+ TREE_VEC_ELT (rhs, 1) = RECUR (TREE_VEC_ELT (rhs, 1));
+ TREE_VEC_ELT (rhs, 2) = RECUR (TREE_VEC_ELT (rhs, 2));
+ cond = build2 (TREE_CODE (cond), TREE_TYPE (cond),
+ lhs, rhs);
+ }
+ else
+ cond = RECUR (cond);
incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
if (TREE_CODE (incr) == MODIFY_EXPR)
{
TREE_OPERAND (cond, 1), iter);
return true;
}
- if (!c_omp_check_loop_iv_exprs (locus, orig_declv,
+ if (!c_omp_check_loop_iv_exprs (locus, orig_declv, i,
TREE_VEC_ELT (declv, i), NULL_TREE,
cond, cp_walk_subtrees))
return true;
tree orig_init;
FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
if (orig_init
- && !c_omp_check_loop_iv_exprs (locus, orig_declv
- ? orig_declv : declv,
+ && !c_omp_check_loop_iv_exprs (locus,
+ orig_declv ? orig_declv : declv, i,
TREE_VEC_ELT (declv, i), orig_init,
NULL_TREE, cp_walk_subtrees))
fail = true;
return NULL;
}
- if (!processing_template_decl)
- {
- init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
- init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init,
- tf_warning_or_error);
- }
+ if (!processing_template_decl && TREE_CODE (init) != TREE_VEC)
+ init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init,
+ tf_warning_or_error);
else
init = build2 (MODIFY_EXPR, void_type_node, decl, init);
- if (cond
- && TREE_SIDE_EFFECTS (cond)
- && COMPARISON_CLASS_P (cond)
- && !processing_template_decl)
- {
- tree t = TREE_OPERAND (cond, 0);
- if (TREE_SIDE_EFFECTS (t)
- && t != decl
- && (TREE_CODE (t) != NOP_EXPR
- || TREE_OPERAND (t, 0) != decl))
- TREE_OPERAND (cond, 0)
- = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
-
- t = TREE_OPERAND (cond, 1);
- if (TREE_SIDE_EFFECTS (t)
- && t != decl
- && (TREE_CODE (t) != NOP_EXPR
- || TREE_OPERAND (t, 0) != decl))
- TREE_OPERAND (cond, 1)
- = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
- }
if (decl == error_mark_node || init == error_mark_node)
return NULL;
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++)
{
- decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i), 0);
+ init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i);
+ decl = TREE_OPERAND (init, 0);
+ cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), i);
incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i);
+ if (!processing_template_decl)
+ {
+ if (TREE_CODE (TREE_OPERAND (init, 1)) == TREE_VEC)
+ {
+ tree t = TREE_VEC_ELT (TREE_OPERAND (init, 1), 1);
+ TREE_VEC_ELT (TREE_OPERAND (init, 1), 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ t = TREE_VEC_ELT (TREE_OPERAND (init, 1), 2);
+ TREE_VEC_ELT (TREE_OPERAND (init, 1), 2)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ else
+ {
+ tree t = TREE_OPERAND (init, 1);
+ TREE_OPERAND (init, 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ if (TREE_CODE (TREE_OPERAND (cond, 1)) == TREE_VEC)
+ {
+ tree t = TREE_VEC_ELT (TREE_OPERAND (cond, 1), 1);
+ TREE_VEC_ELT (TREE_OPERAND (cond, 1), 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ t = TREE_VEC_ELT (TREE_OPERAND (cond, 1), 2);
+ TREE_VEC_ELT (TREE_OPERAND (cond, 1), 2)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ else
+ {
+ tree t = TREE_OPERAND (cond, 1);
+ TREE_OPERAND (cond, 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ }
+
if (TREE_CODE (incr) != MODIFY_EXPR)
continue;
dump_generic_node (buffer, gimple_omp_for_index (gs, i), spc,
flags, false);
pp_string (buffer, " = ");
- dump_generic_node (buffer, gimple_omp_for_initial (gs, i), spc,
- flags, false);
+ tree init = gimple_omp_for_initial (gs, i);
+ if (TREE_CODE (init) != TREE_VEC)
+ dump_generic_node (buffer, init, spc, flags, false);
+ else
+ dump_omp_loop_non_rect_expr (buffer, init, spc, flags);
pp_string (buffer, "; ");
dump_generic_node (buffer, gimple_omp_for_index (gs, i), spc,
gcc_unreachable ();
}
pp_space (buffer);
- dump_generic_node (buffer, gimple_omp_for_final (gs, i), spc,
- flags, false);
+ tree cond = gimple_omp_for_final (gs, i);
+ if (TREE_CODE (cond) != TREE_VEC)
+ dump_generic_node (buffer, cond, spc, flags, false);
+ else
+ dump_omp_loop_non_rect_expr (buffer, cond, spc, flags);
pp_string (buffer, "; ");
dump_generic_node (buffer, gimple_omp_for_index (gs, i), spc,
switch (TREE_CODE (for_stmt))
{
case OMP_FOR:
+ if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
+ {
+ if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
+ OMP_CLAUSE_SCHEDULE))
+ error_at (EXPR_LOCATION (for_stmt),
+ "%qs clause may not appear on non-rectangular %qs",
+ "schedule", "for");
+ if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
+ error_at (EXPR_LOCATION (for_stmt),
+ "%qs clause may not appear on non-rectangular %qs",
+ "ordered", "for");
+ }
+ break;
case OMP_DISTRIBUTE:
+ if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
+ && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
+ OMP_CLAUSE_DIST_SCHEDULE))
+ error_at (EXPR_LOCATION (for_stmt),
+ "%qs clause may not appear on non-rectangular %qs",
+ "dist_schedule", "distribute");
break;
case OACC_LOOP:
ort = ORT_ACC;
else
var = decl;
- tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
- is_gimple_val, fb_rvalue, false);
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
+ {
+ tree lb = TREE_OPERAND (t, 1);
+ tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
+ is_gimple_val, fb_rvalue, false);
+ ret = MIN (ret, tret);
+ tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
+ is_gimple_val, fb_rvalue, false);
+ }
+ else
+ tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
+ is_gimple_val, fb_rvalue, false);
ret = MIN (ret, tret);
if (ret == GS_ERROR)
return ret;
gcc_assert (COMPARISON_CLASS_P (t));
gcc_assert (TREE_OPERAND (t, 0) == decl);
- tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
- is_gimple_val, fb_rvalue, false);
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
+ {
+ tree ub = TREE_OPERAND (t, 1);
+ tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
+ is_gimple_val, fb_rvalue, false);
+ ret = MIN (ret, tret);
+ tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
+ is_gimple_val, fb_rvalue, false);
+ }
+ else
+ tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
+ is_gimple_val, fb_rvalue, false);
ret = MIN (ret, tret);
/* Handle OMP_FOR_INCR. */
pop_gimplify_context (bind);
}
}
+ if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
+ for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
+ {
+ t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
+ gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
+ && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
+ TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
+ t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
+ gcc_assert (COMPARISON_CLASS_P (t));
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
+ && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
+ TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
+ }
}
BITMAP_FREE (has_decl_expr);
t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
+ if (OMP_FOR_NON_RECTANGULAR (for_stmt))
+ for (int j = i + 1;
+ j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
+ {
+ t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
+ gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
+ && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
+ {
+ TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
+ TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
+ }
+ t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
+ gcc_assert (COMPARISON_CLASS_P (t));
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
+ && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
+ {
+ TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
+ TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
+ }
+ }
}
gimplify_adjust_omp_clauses (pre_p, for_body,
expand_omp_for_generic (region, &fd, BUILT_IN_NONE, BUILT_IN_NONE,
NULL_TREE, inner_stmt);
else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
- expand_omp_simd (region, &fd);
+ {
+ if (fd.non_rect)
+ sorry_at (gimple_location (fd.for_stmt),
+ "non-rectangular %<simd%> not supported yet");
+ expand_omp_simd (region, &fd);
+ }
else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
{
- gcc_assert (!inner_stmt);
+ gcc_assert (!inner_stmt && !fd.non_rect);
expand_oacc_for (region, &fd);
}
else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
{
+ if (fd.non_rect)
+ sorry_at (gimple_location (fd.for_stmt),
+ "non-rectangular %<taskloop%> not supported yet");
if (gimple_omp_for_combined_into_p (fd.for_stmt))
expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
else
else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
&& !fd.have_ordered)
{
+ if (fd.non_rect)
+ sorry_at (gimple_location (fd.for_stmt),
+ "non-rectangular OpenMP loops not supported yet");
if (fd.chunk_size == NULL)
expand_omp_for_static_nochunk (region, &fd, inner_stmt);
else
tree sched_arg = NULL_TREE;
gcc_assert (gimple_omp_for_kind (fd.for_stmt)
- == GF_OMP_FOR_KIND_FOR);
+ == GF_OMP_FOR_KIND_FOR && !fd.non_rect);
if (fd.chunk_size == NULL
&& fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
fd.chunk_size = integer_zero_node;
fd->have_pointer_condtemp = false;
fd->have_scantemp = false;
fd->have_nonctrl_scantemp = false;
+ fd->non_rect = false;
fd->lastprivate_conditional = 0;
fd->tiling = NULL_TREE;
fd->collapse = 1;
|| TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
loop->n1 = gimple_omp_for_initial (for_stmt, i);
+ loop->m1 = NULL_TREE;
+ loop->m2 = NULL_TREE;
+ loop->outer = 0;
+ if (TREE_CODE (loop->n1) == TREE_VEC)
+ {
+ for (int j = i - 1; j >= 0; j--)
+ if (TREE_VEC_ELT (loop->n1, 0) == gimple_omp_for_index (for_stmt, j))
+ {
+ loop->outer = i - j;
+ break;
+ }
+ gcc_assert (loop->outer);
+ loop->m1 = TREE_VEC_ELT (loop->n1, 1);
+ loop->n1 = TREE_VEC_ELT (loop->n1, 2);
+ fd->non_rect = true;
+ }
loop->cond_code = gimple_omp_for_cond (for_stmt, i);
loop->n2 = gimple_omp_for_final (for_stmt, i);
gcc_assert (loop->cond_code != NE_EXPR
|| (gimple_omp_for_kind (for_stmt)
!= GF_OMP_FOR_KIND_OACC_LOOP));
+ if (TREE_CODE (loop->n2) == TREE_VEC)
+ {
+ if (loop->outer)
+ gcc_assert (TREE_VEC_ELT (loop->n2, 0)
+ == gimple_omp_for_index (for_stmt, i - loop->outer));
+ else
+ for (int j = i - 1; j >= 0; j--)
+ if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
+ {
+ loop->outer = i - j;
+ break;
+ }
+ gcc_assert (loop->outer);
+ loop->m2 = TREE_VEC_ELT (loop->n2, 1);
+ loop->n2 = TREE_VEC_ELT (loop->n2, 2);
+ fd->non_rect = true;
+ }
t = gimple_omp_for_incr (for_stmt, i);
gcc_assert (TREE_OPERAND (t, 0) == var);
= build_nonstandard_integer_type
(TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
}
+ else if (loop->m1 || loop->m2)
+ /* Non-rectangular loops should use static schedule and no
+ ordered clause. */
+ gcc_unreachable ();
else if (iter_type != long_long_unsigned_type_node)
{
if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
if (collapse_count && *collapse_count == NULL)
{
- t = fold_binary (loop->cond_code, boolean_type_node,
- fold_convert (TREE_TYPE (loop->v), loop->n1),
- fold_convert (TREE_TYPE (loop->v), loop->n2));
+ if (loop->m1 || loop->m2)
+ t = NULL_TREE;
+ else
+ t = fold_binary (loop->cond_code, boolean_type_node,
+ fold_convert (TREE_TYPE (loop->v), loop->n1),
+ fold_convert (TREE_TYPE (loop->v), loop->n2));
if (t && integer_zerop (t))
count = build_zero_cst (long_long_unsigned_type_node);
else if ((i == 0 || count != NULL_TREE)
&& TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
+ && loop->m1 == NULL_TREE
+ && loop->m2 == NULL_TREE
&& TREE_CONSTANT (loop->n1)
&& TREE_CONSTANT (loop->n2)
&& TREE_CODE (loop->step) == INTEGER_CST)
fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
fd->loop.n2 = *collapse_count;
fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
+ fd->loop.m1 = NULL_TREE;
+ fd->loop.m2 = NULL_TREE;
+ fd->loop.outer = 0;
fd->loop.cond_code = LT_EXPR;
}
else if (loops)
};
/* A structure holding the elements of:
- for (V = N1; V cond N2; V += STEP) [...] */
+ for (V = N1; V cond N2; V += STEP) [...]
+ or for non-rectangular loops:
+ for (V = M1 * W + N1; V cond M2 * W + N2; V += STEP;
+ where W is V of the OUTER-th loop (e.g. for OUTER 1 it is the
+ the index of the immediately surrounding loop). */
struct omp_for_data_loop
{
- tree v, n1, n2, step;
+ tree v, n1, n2, step, m1, m2;
+ int outer;
enum tree_code cond_code;
};
int ordered;
bool have_nowait, have_ordered, simd_schedule, have_reductemp;
bool have_pointer_condtemp, have_scantemp, have_nonctrl_scantemp;
+ bool non_rect;
int lastprivate_conditional;
unsigned char sched_modifiers;
enum omp_clause_schedule_kind sched_kind;
for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
{
rhs_p = gimple_omp_for_initial_ptr (stmt, i);
- if (!is_gimple_min_invariant (*rhs_p))
+ if (TREE_CODE (*rhs_p) == TREE_VEC)
+ {
+ if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
+ TREE_VEC_ELT (*rhs_p, 1)
+ = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
+ if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
+ TREE_VEC_ELT (*rhs_p, 1)
+ = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
+ }
+ else if (!is_gimple_min_invariant (*rhs_p))
*rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (*rhs_p);
rhs_p = gimple_omp_for_final_ptr (stmt, i);
- if (!is_gimple_min_invariant (*rhs_p))
+ if (TREE_CODE (*rhs_p) == TREE_VEC)
+ {
+ if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
+ TREE_VEC_ELT (*rhs_p, 1)
+ = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
+ if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
+ TREE_VEC_ELT (*rhs_p, 1)
+ = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
+ }
+ else if (!is_gimple_min_invariant (*rhs_p))
*rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (*rhs_p);
+2021-02-09 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ Backport from mainline
+ 2020-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/loop-6.c: New test.
+ * gcc.dg/gomp/loop-1.c: Don't expect diagnostics on valid
+ non-rectangular loops.
+ * gcc.dg/gomp/loop-2.c: New test.
+ * g++.dg/gomp/loop-1.C: Don't expect diagnostics on valid
+ non-rectangular loops.
+ * g++.dg/gomp/loop-2.C: Likewise.
+ * g++.dg/gomp/loop-5.C: New test.
+ * g++.dg/gomp/loop-6.C: New test.
+
2021-01-22 Kwok Cheung Yeung <kcy@codesourcery.com>
Backport from mainline
--- /dev/null
+int bar (int);
+int baz (int *);
+
+void
+f1 (int x)
+{
+ int i = 0, j = 0, k = 0;
+ long long l = 0;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = i * i; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ ;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = i + 3; j < (i + 1) * 2; j += 2) /* { dg-error "condition expression refers to iteration variable" } */
+ ;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = (i + 1) * 2; j < i * 8; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ ;
+ #pragma omp for collapse(3)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = 0; j < 16; j++)
+ for (k = i + j; k < 32; k++) /* { dg-error "initializer expression refers to iteration variable" } */
+ ;
+ #pragma omp for collapse(2)
+ for (l = 0; l < 16; l++)
+ for (j = 0; j < l; j++) /* { dg-error "outer iteration variable 'l' used in condition expression has type other than 'int'" } */
+ ;
+ #pragma omp for collapse(2) /* { dg-error "outer iteration variable 'l' used in initializer expression has type other than 'int'" "" { target c } } */
+ for (l = 0; l < 16; l++) /* { dg-error "outer iteration variable 'l' used in initializer expression has type other than 'int'" "" { target c++ } } */
+ for (j = 7LL * l; j < 32; j++)
+ ;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = i + 3; j < i * 2 + 2; j += 2)
+ ;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = i * 2 + 2; j < i * 6 + 2; j += 2)
+ ;
+ #pragma omp for collapse(3)
+ for (i = 0; i < 16; i = i + 2)
+ for (j = 0; j < 16; j++)
+ for (k = 14 + 7 * i; k < 32 * j; k++) /* { dg-error "two different outer iteration variables 'i' and 'j' used in a single loop" } */
+ ;
+ #pragma omp for schedule(static, 2) collapse(2) /* { dg-error "'schedule' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+ #pragma omp for schedule(static) collapse(2) /* { dg-error "'schedule' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+ #pragma omp for schedule(dynamic, 5) collapse(2) /* { dg-error "'schedule' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+ #pragma omp for ordered collapse(2) /* { dg-error "'ordered' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+ #pragma omp for ordered collapse(2) /* { dg-error "'ordered' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+ #pragma omp for ordered (3) collapse (2) /* { dg-error "'ordered' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 64; i++)
+ for (j = 0; j < i; j++)
+ for (k = 0; k < 64; k++)
+ {
+ #pragma omp ordered depend (sink: i - 1, j - 2, k - 3)
+ #pragma omp ordered depend (source)
+ }
+ #pragma omp for ordered (3) collapse (2) /* { dg-error "'ordered' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 64; i++)
+ for (j = 0; j < 64; j++)
+ for (k = i; k < 64; k++)
+ {
+ #pragma omp ordered depend (sink: i - 1, j - 2, k - 3)
+ #pragma omp ordered depend (source)
+ }
+ #pragma omp for simd schedule(simd: static) collapse(2) /* { dg-error "'schedule' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+}
+
+void
+f2 (void)
+{
+ int i = 0, j = 0;
+ #pragma omp distribute dist_schedule(static, 4) collapse(2) /* { dg-error "'dist_schedule' clause may not appear on non-rectangular 'distribute'" } */
+ for (i = 0; i < 64; i++)
+ for (j = i; j < 64; j++)
+ ;
+ #pragma omp distribute collapse(2) dist_schedule(static) /* { dg-error "'dist_schedule' clause may not appear on non-rectangular 'distribute'" } */
+ for (i = 0; i < 64; i++)
+ for (j = i; j < 64; j++)
+ ;
+ #pragma omp distribute parallel for simd schedule(simd: static) collapse(2) /* { dg-error "'schedule' clause may not appear on non-rectangular 'for'" } */
+ for (i = 0; i < 16; i++)
+ for (j = 1; j < i; j++)
+ ;
+ #pragma omp distribute parallel for simd collapse(2) dist_schedule(static) /* { dg-error "'dist_schedule' clause may not appear on non-rectangular 'distribute'" } */
+ for (i = 0; i < 64; i++)
+ for (j = i; j < 64; j++)
+ ;
+ #pragma omp distribute simd collapse(2) dist_schedule(static) /* { dg-error "'dist_schedule' clause may not appear on non-rectangular 'distribute'" } */
+ for (i = 0; i < 64; i++)
+ for (j = i; j < 64; j++)
+ ;
+}
for (j = 0; j < 16; j++)
;
#pragma omp for collapse(2)
- for (i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (i = 0; i < 16; i = i + 2)
for (j = i; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i = i + 2)
- for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (j = i + 3; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
- for (j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (j = 0; j < i; j++)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
- for (j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (j = 0; j < i + 4; j++)
;
#pragma omp for collapse(2)
for (i = 0; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
for (int j = 0; j < 16; j += 2)
;
#pragma omp for collapse(2)
- for (int i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (int i = 0; i < 16; i = i + 2)
for (int j = i; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i = i + 2)
- for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (int j = i + 3; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
- for (int j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (int j = 0; j < i; j++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
- for (int j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (int j = 0; j < i + 4; j++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
for (j = 0; j < 16; j++)
;
#pragma omp for collapse(2)
- for (i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (i = 0; i < 16; i = i + 2)
for (j = i; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i = i + 2)
- for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (j = i + 3; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
- for (j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (j = 0; j < i; j++)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
- for (j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (j = 0; j < i + 4; j++)
;
#pragma omp for collapse(2)
for (i = 0; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
for (int j = 0; j < 16; j += 2)
;
#pragma omp for collapse(2)
- for (int i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (int i = 0; i < 16; i = i + 2)
for (int j = i; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i = i + 2)
- for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (int j = i + 3; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
- for (int j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (int j = 0; j < i; j++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
- for (int j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (int j = 0; j < i + 4; j++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
--- /dev/null
+void
+foo ()
+{
+ int i = 0;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i++) // { dg-error "the same loop iteration variables 'i' used in multiple associated loops" }
+ for (i = 1; i < 32; i++)
+ ;
+ #pragma omp taskloop collapse(2)
+ for (int j = 0; j < 16; j++) // { dg-error "the same loop iteration variables 'j' used in multiple associated loops" }
+ for (j = 0; j < 16; j++)
+ ;
+}
+
+template <int N>
+void
+bar ()
+{
+ int i = 0;
+ #pragma omp for collapse(2)
+ for (i = 0; i < 16; i++) // { dg-error "the same loop iteration variables 'i' used in multiple associated loops" }
+ for (i = 1; i < 32; i++)
+ ;
+ #pragma omp taskloop collapse(2)
+ for (int j = 0; j < 16; j++) // { dg-error "the same loop iteration variables 'j' used in multiple associated loops" }
+ for (j = 0; j < 16; j++)
+ ;
+}
+
+template <typename T>
+void
+baz ()
+{
+ T i = 0;
+ #pragma omp for collapse(2) // { dg-error "the same loop iteration variables 'i' used in multiple associated loops" }
+ for (i = 0; i < 16; i++)
+ for (i = 1; i < 32; i++)
+ ;
+ #pragma omp taskloop collapse(2) // { dg-error "the same loop iteration variables 'j' used in multiple associated loops" }
+ for (T j = 0; j < 16; j++)
+ for (j = 0; j < 16; j++)
+ ;
+}
+
+void
+test ()
+{
+ bar <0> ();
+ baz <int> ();
+}
--- /dev/null
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+
+template <typename T> bool operator == (I<T> &, I<T> &);
+template <typename T> bool operator == (const I<T> &, const I<T> &);
+template <typename T> bool operator != (I<T> &, I<T> &);
+template <typename T> bool operator != (const I<T> &, const I<T> &);
+template <typename T> bool operator < (I<T> &, I<T> &);
+template <typename T> bool operator < (const I<T> &, const I<T> &);
+template <typename T> bool operator <= (I<T> &, I<T> &);
+template <typename T> bool operator <= (const I<T> &, const I<T> &);
+template <typename T> bool operator > (I<T> &, I<T> &);
+template <typename T> bool operator > (const I<T> &, const I<T> &);
+template <typename T> bool operator >= (I<T> &, I<T> &);
+template <typename T> bool operator >= (const I<T> &, const I<T> &);
+template <typename T> typename I<T>::difference_type operator - (I<T> &, I<T> &);
+template <typename T> typename I<T>::difference_type operator - (const I<T> &, const I<T> &);
+template <typename T> I<T> operator + (typename I<T>::difference_type, const I<T> &);
+
+void
+f1 (I<int> &x, I<int> &y)
+{
+ I<int> i;
+ #pragma omp for collapse(2)
+ for (i = x; i < y; i++) // { dg-error "the same loop iteration variables 'i' used in multiple associated loops" }
+ for (i = x; i < y; i++)
+ ;
+ #pragma omp for collapse(2)
+ for (I<int> j = x; j < y; j++)// { dg-error "the same loop iteration variables 'j' used in multiple associated loops" }
+ for (j = y; j > x; j--)
+ ;
+}
for (i = j; i < 16; i = i + 2)
for (j = 0; j < 16; j++)
;
- #pragma omp for collapse(2) /* { dg-error "initializer expression refers to iteration variable" } */
+ #pragma omp for collapse(2)
for (i = 0; i < 16; i = i + 2)
for (j = i; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i = i + 2)
- for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (j = i + 3; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
- for (j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (j = 0; j < i; j++)
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
- for (j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (j = 0; j < i + 4; j++)
;
#pragma omp for collapse(2)
for (i = 0; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
for (int i = 0; i < 16; i = i + 2)
for (int j = 0; j < 16; j += 2)
;
- #pragma omp for collapse(2) /* { dg-error "initializer expression refers to iteration variable" } */
+ #pragma omp for collapse(2)
for (int i = 0; i < 16; i = i + 2)
for (int j = i; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i = i + 2)
- for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+ for (int j = i + 3; j < 16; j += 2)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
- for (int j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (int j = 0; j < i; j++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
- for (int j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+ for (int j = 0; j < i + 4; j++)
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
--- /dev/null
+void
+foo (void)
+{
+ int i = 0;
+ #pragma omp for collapse(2) /* { dg-error "the same loop iteration variables 'i' used in multiple associated loops" } */
+ for (i = 0; i < 16; i++)
+ for (i = 1; i < 32; i++)
+ ;
+ #pragma omp taskloop collapse(2) /* { dg-error "the same loop iteration variables 'j' used in multiple associated loops" } */
+ for (int j = 0; j < 16; j++)
+ for (j = 0; j < 16; j++)
+ ;
+}
}
pp_right_bracket (pp);
}
- }
+}
+
+/* Helper function for dump_generic_node. Dump INIT or COND expression for
+ OpenMP loop non-rectangular iterators. */
+
+void
+dump_omp_loop_non_rect_expr (pretty_printer *pp, tree node, int spc,
+ dump_flags_t flags)
+{
+ gcc_assert (TREE_CODE (node) == TREE_VEC);
+ dump_generic_node (pp, TREE_VEC_ELT (node, 0), spc, flags, false);
+ pp_string (pp, " * ");
+ if (op_prio (TREE_VEC_ELT (node, 1)) <= op_code_prio (MULT_EXPR))
+ {
+ pp_left_paren (pp);
+ dump_generic_node (pp, TREE_VEC_ELT (node, 1), spc, flags, false);
+ pp_right_paren (pp);
+ }
+ else
+ dump_generic_node (pp, TREE_VEC_ELT (node, 1), spc, flags, false);
+ pp_string (pp, " + ");
+ if (op_prio (TREE_VEC_ELT (node, 1)) <= op_code_prio (PLUS_EXPR))
+ {
+ pp_left_paren (pp);
+ dump_generic_node (pp, TREE_VEC_ELT (node, 2), spc, flags, false);
+ pp_right_paren (pp);
+ }
+ else
+ dump_generic_node (pp, TREE_VEC_ELT (node, 2), spc, flags, false);
+}
/* Dump the node NODE on the pretty_printer PP, SPC spaces of
indent. FLAGS specifies details to show in the dump (see TDF_* in
spc += 2;
newline_and_indent (pp, spc);
pp_string (pp, "for (");
- dump_generic_node (pp,
- TREE_VEC_ELT (OMP_FOR_INIT (node), i),
- spc, flags, false);
+ tree init = TREE_VEC_ELT (OMP_FOR_INIT (node), i);
+ if (TREE_CODE (init) != MODIFY_EXPR
+ || TREE_CODE (TREE_OPERAND (init, 1)) != TREE_VEC)
+ dump_generic_node (pp, init, spc, flags, false);
+ else
+ {
+ dump_generic_node (pp, TREE_OPERAND (init, 0),
+ spc, flags, false);
+ pp_string (pp, " = ");
+ dump_omp_loop_non_rect_expr (pp, TREE_OPERAND (init, 1),
+ spc, flags);
+ }
pp_string (pp, "; ");
- dump_generic_node (pp,
- TREE_VEC_ELT (OMP_FOR_COND (node), i),
- spc, flags, false);
+ tree cond = TREE_VEC_ELT (OMP_FOR_COND (node), i);
+ if (!COMPARISON_CLASS_P (cond)
+ || TREE_CODE (TREE_OPERAND (cond, 1)) != TREE_VEC)
+ dump_generic_node (pp, cond, spc, flags, false);
+ else
+ {
+ dump_generic_node (pp, TREE_OPERAND (cond, 0),
+ spc, flags, false);
+ const char *op = op_symbol (cond);
+ pp_space (pp);
+ pp_string (pp, op);
+ pp_space (pp);
+ dump_omp_loop_non_rect_expr (pp, TREE_OPERAND (cond, 1),
+ spc, flags);
+ }
pp_string (pp, "; ");
dump_generic_node (pp,
TREE_VEC_ELT (OMP_FOR_INCR (node), i),
extern void dump_omp_clauses (pretty_printer *, tree, int, dump_flags_t);
extern void dump_omp_atomic_memory_order (pretty_printer *,
enum omp_memory_order);
+extern void dump_omp_loop_non_rect_expr (pretty_printer *, tree, int,
+ dump_flags_t);
extern int dump_generic_node (pretty_printer *, tree, int, dump_flags_t, bool);
extern void print_declaration (pretty_printer *, tree, int, dump_flags_t);
extern int op_code_prio (enum tree_code);
!= UNKNOWN_LOCATION)
#define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
+/* True on OMP_FOR and other OpenMP/OpenACC looping constructs if the loop nest
+ is non-rectangular. */
+#define OMP_FOR_NON_RECTANGULAR(NODE) \
+ (OMP_LOOPING_CHECK (NODE)->base.private_flag)
+
/* True on an OMP_SECTION statement that was the last lexical member.
This status is meaningful in the implementation of lastprivate. */
#define OMP_SECTION_LAST(NODE) \