openmp: Add support for OpenMP 5.1 structured-block-sequences
Related to this is the addition of structured-block-sequence in OpenMP 5.1, which doesn't change anything for Fortran, but for C/C++ allows multiple statements instead of just one possibly compound around the separating directives (section and scan). I've also made some updates to the OpenMP 5.1 support list in libgomp.texi. 2021-10-09 Jakub Jelinek <jakub@redhat.com> gcc/c/ * c-parser.c (c_parser_omp_structured_block_sequence): New function. (c_parser_omp_scan_loop_body): Use it. (c_parser_omp_sections_scope): Likewise. gcc/cp/ * parser.c (cp_parser_omp_structured_block): Remove disallow_omp_attrs argument. (cp_parser_omp_structured_block_sequence): New function. (cp_parser_omp_scan_loop_body): Use it. (cp_parser_omp_sections_scope): Likewise. gcc/testsuite/ * c-c++-common/gomp/sections1.c (foo): Don't expect errors on multiple statements in between section directive(s). Add testcases for invalid no statements in between section directive(s). * gcc.dg/gomp/sections-2.c (foo): Don't expect errors on multiple statements in between section directive(s). * g++.dg/gomp/sections-2.C (foo): Likewise. * g++.dg/gomp/attrs-6.C (foo): Add testcases for multiple statements in between section directive(s). (bar): Add testcases for multiple statements in between scan directive. * g++.dg/gomp/attrs-7.C (bar): Adjust expected error recovery. libgomp/ * libgomp.texi (OpenMP 5.1): Mention implemented support for structured block sequences in C/C++. Mention support for unconstrained/reproducible modifiers on order clause. Mention partial (C/C++ only) support of extentensions to atomics construct. Mention partial (C/C++ on clause only) support of align/allocator modifiers on allocate clause.
This commit is contained in:
parent
0d788c358b
commit
875124eb08
8 changed files with 173 additions and 30 deletions
|
@ -18976,6 +18976,31 @@ c_parser_omp_flush (c_parser *parser)
|
|||
c_finish_omp_flush (loc, mo);
|
||||
}
|
||||
|
||||
/* Parse an OpenMP structured block sequence. KIND is the corresponding
|
||||
separating directive. */
|
||||
|
||||
static tree
|
||||
c_parser_omp_structured_block_sequence (c_parser *parser,
|
||||
enum pragma_kind kind)
|
||||
{
|
||||
tree stmt = push_stmt_list ();
|
||||
c_parser_statement (parser, NULL);
|
||||
do
|
||||
{
|
||||
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
|
||||
break;
|
||||
if (c_parser_next_token_is (parser, CPP_EOF))
|
||||
break;
|
||||
|
||||
if (kind != PRAGMA_NONE
|
||||
&& c_parser_peek_token (parser)->pragma_kind == kind)
|
||||
break;
|
||||
c_parser_statement (parser, NULL);
|
||||
}
|
||||
while (1);
|
||||
return pop_stmt_list (stmt);
|
||||
}
|
||||
|
||||
/* OpenMP 5.0:
|
||||
|
||||
scan-loop-body:
|
||||
|
@ -18997,7 +19022,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
|
|||
return;
|
||||
}
|
||||
|
||||
substmt = c_parser_omp_structured_block (parser, NULL);
|
||||
substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
|
||||
substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
|
||||
SET_EXPR_LOCATION (substmt, loc);
|
||||
add_stmt (substmt);
|
||||
|
@ -19032,7 +19057,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
|
|||
error ("expected %<#pragma omp scan%>");
|
||||
|
||||
clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
|
||||
substmt = c_parser_omp_structured_block (parser, NULL);
|
||||
substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
|
||||
substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
|
||||
SET_EXPR_LOCATION (substmt, loc);
|
||||
add_stmt (substmt);
|
||||
|
@ -19860,6 +19885,8 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
|
|||
section-directive[opt] structured-block
|
||||
section-sequence section-directive structured-block
|
||||
|
||||
OpenMP 5.1 allows structured-block-sequence instead of structured-block.
|
||||
|
||||
SECTIONS_LOC is the location of the #pragma omp sections. */
|
||||
|
||||
static tree
|
||||
|
@ -19881,7 +19908,8 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
|
|||
|
||||
if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
|
||||
{
|
||||
substmt = c_parser_omp_structured_block (parser, NULL);
|
||||
substmt = c_parser_omp_structured_block_sequence (parser,
|
||||
PRAGMA_OMP_SECTION);
|
||||
substmt = build1 (OMP_SECTION, void_type_node, substmt);
|
||||
SET_EXPR_LOCATION (substmt, loc);
|
||||
add_stmt (substmt);
|
||||
|
@ -19907,7 +19935,8 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
|
|||
error_suppress = true;
|
||||
}
|
||||
|
||||
substmt = c_parser_omp_structured_block (parser, NULL);
|
||||
substmt = c_parser_omp_structured_block_sequence (parser,
|
||||
PRAGMA_OMP_SECTION);
|
||||
substmt = build1 (OMP_SECTION, void_type_node, substmt);
|
||||
SET_EXPR_LOCATION (substmt, loc);
|
||||
add_stmt (substmt);
|
||||
|
|
|
@ -40136,14 +40136,12 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
|
|||
}
|
||||
|
||||
static tree
|
||||
cp_parser_omp_structured_block (cp_parser *parser, bool *if_p,
|
||||
bool disallow_omp_attrs = true)
|
||||
cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
|
||||
{
|
||||
tree stmt = begin_omp_structured_block ();
|
||||
unsigned int save = cp_parser_begin_omp_structured_block (parser);
|
||||
|
||||
if (disallow_omp_attrs)
|
||||
parser->omp_attrs_forbidden_p = true;
|
||||
parser->omp_attrs_forbidden_p = true;
|
||||
cp_parser_statement (parser, NULL_TREE, false, if_p);
|
||||
|
||||
cp_parser_end_omp_structured_block (parser, save);
|
||||
|
@ -42001,6 +41999,43 @@ cp_parser_omp_section_scan (cp_parser *parser, const char *directive,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Parse an OpenMP structured block sequence. KIND is the corresponding
|
||||
separating directive. */
|
||||
|
||||
static tree
|
||||
cp_parser_omp_structured_block_sequence (cp_parser *parser,
|
||||
enum pragma_kind kind)
|
||||
{
|
||||
tree stmt = begin_omp_structured_block ();
|
||||
unsigned int save = cp_parser_begin_omp_structured_block (parser);
|
||||
|
||||
cp_parser_statement (parser, NULL_TREE, false, NULL);
|
||||
while (true)
|
||||
{
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
if (token->type == CPP_CLOSE_BRACE
|
||||
|| token->type == CPP_EOF
|
||||
|| token->type == CPP_PRAGMA_EOL
|
||||
|| (token->type == CPP_KEYWORD && token->keyword == RID_AT_END)
|
||||
|| (kind != PRAGMA_NONE
|
||||
&& cp_parser_pragma_kind (token) == kind))
|
||||
break;
|
||||
|
||||
if (kind != PRAGMA_NONE
|
||||
&& cp_parser_omp_section_scan (parser,
|
||||
kind == PRAGMA_OMP_SCAN
|
||||
? "scan" : "section", false))
|
||||
break;
|
||||
|
||||
cp_parser_statement (parser, NULL_TREE, false, NULL);
|
||||
}
|
||||
|
||||
cp_parser_end_omp_structured_block (parser, save);
|
||||
return finish_omp_structured_block (stmt);
|
||||
}
|
||||
|
||||
|
||||
/* OpenMP 5.0:
|
||||
|
||||
scan-loop-body:
|
||||
|
@ -42015,11 +42050,10 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
|
|||
if (!braces.require_open (parser))
|
||||
return;
|
||||
|
||||
substmt = cp_parser_omp_structured_block (parser, NULL, false);
|
||||
substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
|
||||
substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
|
||||
add_stmt (substmt);
|
||||
|
||||
cp_parser_omp_section_scan (parser, "scan", false);
|
||||
cp_token *tok = cp_lexer_peek_token (parser->lexer);
|
||||
if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
|
||||
{
|
||||
|
@ -42055,7 +42089,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
|
|||
error ("expected %<#pragma omp scan%>");
|
||||
|
||||
clauses = finish_omp_clauses (clauses, C_ORT_OMP);
|
||||
substmt = cp_parser_omp_structured_block (parser, NULL, false);
|
||||
substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
|
||||
substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
|
||||
clauses);
|
||||
add_stmt (substmt);
|
||||
|
@ -42924,7 +42958,8 @@ cp_parser_omp_sections_scope (cp_parser *parser)
|
|||
!= PRAGMA_OMP_SECTION
|
||||
&& !cp_parser_omp_section_scan (parser, "section", true))
|
||||
{
|
||||
substmt = cp_parser_omp_structured_block (parser, NULL, false);
|
||||
substmt = cp_parser_omp_structured_block_sequence (parser,
|
||||
PRAGMA_OMP_SECTION);
|
||||
substmt = build1 (OMP_SECTION, void_type_node, substmt);
|
||||
add_stmt (substmt);
|
||||
}
|
||||
|
@ -42951,7 +42986,8 @@ cp_parser_omp_sections_scope (cp_parser *parser)
|
|||
error_suppress = true;
|
||||
}
|
||||
|
||||
substmt = cp_parser_omp_structured_block (parser, NULL, false);
|
||||
substmt = cp_parser_omp_structured_block_sequence (parser,
|
||||
PRAGMA_OMP_SECTION);
|
||||
substmt = build1 (OMP_SECTION, void_type_node, substmt);
|
||||
add_stmt (substmt);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ foo ()
|
|||
#pragma omp sections
|
||||
{
|
||||
bar (12);
|
||||
bar (13); /* { dg-error "pragma omp section" } */
|
||||
bar (13);
|
||||
#pragma omp section
|
||||
bar (14);
|
||||
}
|
||||
|
@ -63,11 +63,29 @@ foo ()
|
|||
bar (15);
|
||||
#pragma omp section
|
||||
bar (16);
|
||||
bar (17); /* { dg-error "pragma omp section" } */
|
||||
bar (17);
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
bar (18);
|
||||
#pragma omp section
|
||||
} /* { dg-error "expression before" } */
|
||||
#pragma omp sections
|
||||
{
|
||||
#pragma omp section
|
||||
#pragma omp section /* { dg-error "may only be used in" } */
|
||||
bar (19);
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
bar (20);
|
||||
#pragma omp section
|
||||
#pragma omp section /* { dg-error "may only be used in" } */
|
||||
bar (21);
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
bar (22);
|
||||
#pragma omp section
|
||||
} /* { dg-error "expression before" } */
|
||||
}
|
||||
|
|
|
@ -26,6 +26,41 @@ foo ()
|
|||
#pragma omp section
|
||||
{ a[3]++; }
|
||||
}
|
||||
#pragma omp parallel sections
|
||||
{
|
||||
#pragma omp section
|
||||
a[0]++;
|
||||
a[4]++;
|
||||
l1: a[5]++;
|
||||
if (a[5] == 42) goto l1;
|
||||
[[omp::directive (section)]] {
|
||||
a[1]++;
|
||||
a[6]++;
|
||||
} [[omp::directive (section)]]
|
||||
a[2]++;
|
||||
a[7]++;
|
||||
#pragma omp section
|
||||
{ a[3]++; }
|
||||
a[8]++;
|
||||
}
|
||||
[[omp::directive (parallel sections)]]
|
||||
{
|
||||
#pragma omp section
|
||||
a[0]++;
|
||||
a[4]++;
|
||||
[[omp::directive (section)]] {
|
||||
a[1]++;
|
||||
a[5]++;
|
||||
} [[omp::directive (section)]]
|
||||
a[2]++;
|
||||
l2: a[6]++;
|
||||
if (a[6] == 42)
|
||||
goto l2;
|
||||
a[7]++;
|
||||
#pragma omp section
|
||||
a[8]++;
|
||||
{ a[3]++; }
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -46,5 +81,23 @@ bar (int a, int *c, int *d, int *e, int *f)
|
|||
#pragma omp scan inclusive (a)
|
||||
d[i] = a;
|
||||
}
|
||||
#pragma omp simd reduction (inscan, +: a)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
int t = a;
|
||||
d[i] = t;
|
||||
[[omp::directive (scan, exclusive (a))]]
|
||||
int u = c[i];
|
||||
a += u;
|
||||
}
|
||||
[[omp::directive (simd reduction (inscan, +: a))]]
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
int t = c[i];
|
||||
a += t;
|
||||
#pragma omp scan inclusive (a)
|
||||
int u = a;
|
||||
d[i] = u;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -29,29 +29,33 @@ bar (int a, int *c, int *d, int *e, int *f)
|
|||
{
|
||||
d[i] = a;
|
||||
[[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]] // { dg-error "must be the only specified attribute on a statement" }
|
||||
a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
}
|
||||
// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
a += c[i]; // { dg-error "expected" }
|
||||
} // { dg-error "expected" }
|
||||
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
a += c[i];
|
||||
[[omp::sequence (directive (scan inclusive (a)), directive (critical))]] // { dg-error "must be the only specified attribute on a statement" }
|
||||
d[i] = a; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
}
|
||||
// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
d[i] = a; // { dg-error "expected" }
|
||||
} // { dg-error "expected" }
|
||||
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
d[i] = a;
|
||||
[[gnu::cold]] [[omp::directive (scan, exclusive (a))]] // { dg-error "must be the only specified attribute on a statement" }
|
||||
a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
}
|
||||
// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
a += c[i]; // { dg-error "expected" }
|
||||
} // { dg-error "expected" }
|
||||
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
d[i] = a;
|
||||
[[omp::directive (scan, exclusive (a)), gnu::cold]] // { dg-error "must be the only specified attribute on a statement" }
|
||||
a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
}
|
||||
// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
|
||||
a += c[i]; // { dg-error "expected" }
|
||||
} // { dg-error "expected" }
|
||||
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
|
|
|
@ -19,11 +19,11 @@ void foo(void)
|
|||
{
|
||||
#pragma omp section
|
||||
bar(2);
|
||||
bar(3); // { dg-error "expected" }
|
||||
bar(3);
|
||||
bar(4);
|
||||
#pragma omp section
|
||||
bar(5);
|
||||
bar(6); // { dg-error "expected" }
|
||||
bar(6);
|
||||
bar(7);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ void foo(void)
|
|||
{
|
||||
#pragma omp section
|
||||
bar(2);
|
||||
bar(3); // { dg-error "expected" }
|
||||
bar(3);
|
||||
bar(4);
|
||||
#pragma omp section
|
||||
bar(5);
|
||||
bar(6); // { dg-error "expected" }
|
||||
bar(6);
|
||||
bar(7);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@ The OpenMP 4.5 specification is fully supported.
|
|||
@item @code{strict} modifier in the @code{grainsize} and @code{num_tasks}
|
||||
clauses of the taskloop construct @tab Y @tab
|
||||
@item @code{align} clause/modifier in @code{allocate} directive/clause
|
||||
and @code{allocator} directive @tab N @tab
|
||||
and @code{allocator} directive @tab P @tab C/C++ on clause only
|
||||
@item @code{thread_limit} clause to @code{target} construct @tab N @tab
|
||||
@item @code{has_device_addr} clause to @code{target} construct @tab N @tab
|
||||
@item iterators in @code{target update} motion clauses and @code{map}
|
||||
|
@ -301,7 +301,7 @@ The OpenMP 4.5 specification is fully supported.
|
|||
@item @code{interop} directive @tab N @tab
|
||||
@item @code{omp_interop_t} object support in runtime routines @tab N @tab
|
||||
@item @code{nowait} clause in @code{taskwait} directive @tab N @tab
|
||||
@item Extensions to the @code{atomic} directive @tab N @tab
|
||||
@item Extensions to the @code{atomic} directive @tab P @tab C/C++ only
|
||||
@item @code{seq_cst} clause on a @code{flush} construct @tab Y @tab
|
||||
@item @code{inoutset} argument to the @code{depend} clause @tab N @tab
|
||||
@item @code{private} and @code{firstprivate} argument to @code{default}
|
||||
|
@ -337,7 +337,10 @@ The OpenMP 4.5 specification is fully supported.
|
|||
|
||||
@multitable @columnfractions .60 .10 .25
|
||||
@headitem Description @tab Status @tab Comments
|
||||
@item Suppport of strictly structured blocks in Fortran @tab N @tab
|
||||
@item Support of strictly structured blocks in Fortran @tab N @tab
|
||||
@item Support of structured block sequences in C/C++ @tab Y @tab
|
||||
@item @code{unconstrained} and @code{reproducible} modifiers on @code{order}
|
||||
clause @tab Y @tab
|
||||
@end multitable
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue