aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/c-omp.c4
-rw-r--r--gcc/c/c-parser.c6
-rw-r--r--gcc/cp/parser.c6
-rw-r--r--gcc/fortran/dump-parse-tree.c2
-rw-r--r--gcc/fortran/gfortran.h4
-rw-r--r--gcc/fortran/openmp.c5
-rw-r--r--gcc/fortran/trans-openmp.c7
-rw-r--r--gcc/omp-general.c16
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-5.f908
-rw-r--r--gcc/tree-pretty-print.c2
-rw-r--r--gcc/tree.h3
11 files changed, 53 insertions, 10 deletions
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 1f07a0a..2849fda 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -2128,6 +2128,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
= OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
+ = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
}
@@ -2139,6 +2141,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
= OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
+ = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
s = C_OMP_CLAUSE_SPLIT_SIMD;
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 21ff25d..a66f43f 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -14626,6 +14626,7 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
tree c;
const char *p;
bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -14636,7 +14637,9 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "unconstrained") == 0)
unconstrained = true;
- else if (strcmp (p, "reproducible") != 0)
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
{
c_parser_error (parser, "expected %<reproducible%> or "
"%<unconstrained%>");
@@ -14661,6 +14664,7 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 04f5a24..c6f1a97 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -37735,6 +37735,7 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
tree c, id;
const char *p;
bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -37747,7 +37748,9 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
p = IDENTIFIER_POINTER (id);
if (strcmp (p, "unconstrained") == 0)
unconstrained = true;
- else if (strcmp (p, "reproducible") != 0)
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
{
cp_parser_error (parser, "expected %<reproducible%> or "
"%<unconstrained%>");
@@ -37778,6 +37781,7 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order", location);
c = build_omp_clause (location, OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 28eb09e..64e04c0 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1634,6 +1634,8 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
fputs (" ORDER(", dumpfile);
if (omp_clauses->order_unconstrained)
fputs ("UNCONSTRAINED:", dumpfile);
+ else if (omp_clauses->order_reproducible)
+ fputs ("REPRODUCIBLE:", dumpfile);
fputs ("CONCURRENT)", dumpfile);
}
if (omp_clauses->ordered)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 7ef835b..c25d1cc 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1491,8 +1491,8 @@ typedef struct gfc_omp_clauses
unsigned inbranch:1, notinbranch:1, nogroup:1;
unsigned sched_simd:1, sched_monotonic:1, sched_nonmonotonic:1;
unsigned simd:1, threads:1, depend_source:1, destroy:1, order_concurrent:1;
- unsigned order_unconstrained:1, capture:1, grainsize_strict:1;
- unsigned num_tasks_strict:1;
+ unsigned order_unconstrained:1, order_reproducible:1, capture:1;
+ unsigned grainsize_strict:1, num_tasks_strict:1;
ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 9ee52d6..6a4ca28 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -2374,8 +2374,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
{
if (m == MATCH_ERROR)
goto error;
- if (gfc_match (" reproducible : concurrent )") == MATCH_YES
- || gfc_match (" concurrent )") == MATCH_YES)
+ if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
+ c->order_reproducible = true;
+ else if (gfc_match (" concurrent )") == MATCH_YES)
;
else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
c->order_unconstrained = true;
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 4ca2c3f..d234d1b 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -3804,6 +3804,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
{
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -5895,6 +5896,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->order_concurrent;
clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
= code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
}
if (mask & GFC_OMP_MASK_PARALLEL)
{
@@ -5951,6 +5954,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->order_concurrent;
clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
= code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_DO].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
}
if (mask & GFC_OMP_MASK_SIMD)
{
@@ -5969,6 +5974,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->order_concurrent;
clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
= code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
/* And this is copied to all. */
clausesa[GFC_OMP_SPLIT_SIMD].if_expr
= code->ext.omp_clauses->if_expr;
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index cc6aecb..1e4c0b2 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -193,6 +193,7 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
== GF_OMP_FOR_KIND_DISTRIBUTE;
bool taskloop = gimple_omp_for_kind (for_stmt)
== GF_OMP_FOR_KIND_TASKLOOP;
+ bool order_reproducible = false;
tree iterv, countv;
fd->for_stmt = for_stmt;
@@ -277,10 +278,25 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
&& !OMP_CLAUSE__SCANTEMP__CONTROL (t))
fd->have_nonctrl_scantemp = true;
break;
+ case OMP_CLAUSE_ORDER:
+ /* FIXME: For OpenMP 5.2 this should change to
+ if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
+ (with the exception of loop construct but that lowers to
+ no schedule/dist_schedule clauses currently). */
+ if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t))
+ order_reproducible = true;
default:
break;
}
+ /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
+ we have either the option to expensively remember at runtime how we've
+ distributed work from first loop and reuse that in following loops with
+ the same number of iterations and schedule, or just force static schedule.
+ OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
+ users can't observe it easily anyway. */
+ if (order_reproducible)
+ fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
if (fd->collapse > 1 || fd->tiling)
fd->loops = loops;
else
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-5.f90 b/gcc/testsuite/gfortran.dg/gomp/order-5.f90
index 4d9e336..0dddb96 100644
--- a/gcc/testsuite/gfortran.dg/gomp/order-5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/order-5.f90
@@ -116,14 +116,14 @@ subroutine f4 (a)
end do
end
-! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(reproducible:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(unconstrained:concurrent\\)" 6 "original"} }
-! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(reproducible:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(unconstrained:concurrent\\)" 6 "original"} }
-! { dg-final { scan-tree-dump-times "#pragma omp for order\\(concurrent\\)" 2 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for order\\(reproducible:concurrent\\)" 2 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp for order\\(unconstrained:concurrent\\)" 2 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp parallel" 12 "original"} }
-! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(reproducible:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(unconstrained:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp taskloop" 2 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp teams" 8 "original"} }
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 35e567c..0b5bdd7 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1165,6 +1165,8 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "order(");
if (OMP_CLAUSE_ORDER_UNCONSTRAINED (clause))
pp_string (pp, "unconstrained:");
+ else if (OMP_CLAUSE_ORDER_REPRODUCIBLE (clause))
+ pp_string (pp, "reproducible:");
pp_string (pp, "concurrent)");
break;
diff --git a/gcc/tree.h b/gcc/tree.h
index 7d1257b..7542d97 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1718,6 +1718,9 @@ class auto_suppress_location_wrappers
/* True for unconstrained modifier on order(concurrent) clause. */
#define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag)
+/* True for reproducible modifier on order(concurrent) clause. */
+#define OMP_CLAUSE_ORDER_REPRODUCIBLE(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER))
#define OMP_CLAUSE_REDUCTION_CODE(NODE) \
(OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \