summaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-06-16 16:31:13 +0200
committerJakub Jelinek <jakub@redhat.com>2020-06-16 16:31:13 +0200
commit1160ec9a141faf1c4c0496c7412c8febeb623962 (patch)
treecccaae90eda1cbae323278675e2df1a186f32ac1 /gcc/c
parentfab46c5df7500f2ce640f98320d47a19d3de8a2f (diff)
openmp: Initial part of OpenMP 5.0 non-rectangular loop support
OpenMP 5.0 adds support for non-rectangular loop collapses, e.g. triangular and more complex. This patch deals just with the diagnostics so that they aren't rejected immediately as before. As the spec generally requires as before that the iteration variable initializer and bound in the comparison as invariant vs. the outermost loop, and just add some exceptional forms that can violate that, we need to avoid folding the expressions until we can detect them and in order to avoid folding it later on, I chose to use a TREE_VEC in those expressions to hold the var_outer * expr1 + expr2 triplet, the patch adds pretty-printing of that, gimplification etc. and just sorry_at during omp expansion for now. The next step will be to implement the different cases of that one by one. 2020-06-16 Jakub Jelinek <jakub@redhat.com> gcc/ * 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. gcc/c-family/ * 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. gcc/c/ * 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. gcc/cp/ * 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. gcc/testsuite/ * 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.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-parser.c54
-rw-r--r--gcc/c/c-tree.h1
-rw-r--r--gcc/c/c-typeck.c35
3 files changed, 70 insertions, 20 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fea6a09f771..7bf91ef91aa 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -7594,6 +7594,8 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
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;
@@ -7633,6 +7635,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
code = BIT_IOR_EXPR;
break;
default:
+ c_in_omp_for = save_in_omp_for;
return lhs;
}
c_parser_consume_token (parser);
@@ -7652,6 +7655,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
ret.original_code = ERROR_MARK;
}
ret.original_type = NULL;
+ c_in_omp_for = save_in_omp_for;
return ret;
}
@@ -18119,8 +18123,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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);
@@ -18158,9 +18164,11 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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 %<;%>");
@@ -18181,19 +18189,13 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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:
@@ -18337,8 +18339,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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))
@@ -18348,6 +18352,40 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
{
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)
{
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 94668866fa2..10938cf0857 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -657,6 +657,7 @@ extern alias_set_type c_get_alias_set (tree);
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;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 385bf3a1c7b..3be3690c6e2 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -71,6 +71,9 @@ int in_sizeof;
/* 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;
@@ -6209,15 +6212,20 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
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);
@@ -7745,12 +7753,15 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
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. */
@@ -12475,7 +12486,7 @@ build_binary_op (location_t location, enum tree_code code,
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;