]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Differentiate between order(concurrent) and order(reproducible:concurrent)
authorJakub Jelinek <jakub@redhat.com>
Fri, 1 Oct 2021 18:00:00 +0000 (20:00 +0200)
committerTobias Burnus <tobias@codesourcery.com>
Fri, 1 Oct 2021 18:00:00 +0000 (20:00 +0200)
While OpenMP 5.1 implies order(concurrent) is the same thing as
order(reproducible:concurrent), this is going to change in OpenMP 5.2, where
essentially order(concurrent) means nothing is stated on whether it is
reproducible or unconstrained (and is determined by other means, e.g. for/do
with schedule static or runtime with static being selected is implicitly
reproducible, distribute with dist_schedule static is implicitly reproducible,
loop is implicitly reproducible) and when the modifier is specified explicitly,
it overrides the implicit behavior either way.
And, when order(reproducible:concurrent) is used with e.g. schedule(dynamic)
or some other schedule that is by definition not reproducible, it is
implementation's duty to ensure it is reproducible, either by remembering how
it scheduled some loop and then replaying the same schedule when seeing loops
with the same directive/schedule/number of iterations, or by overriding the
schedule to some reproducible one.

This patch doesn't implement the 5.2 wording just yet, but in the FEs
differentiates between the 3 states - no explicit modifier, explicit reproducible
or explicit unconstrainted, so that the middle-end can easily switch any time.
Instead it follows the 5.1 wording where both order(concurrent) (implicit or
explicit) or order(reproducible:concurrent) imply reproducibility.
And, it implements the easier method, when for/do should be reproducible, it
just chooses static schedule.  order(concurrent) implies no OpenMP APIs in the
loop body nor threadprivate vars, so the exact scheduling isn't (easily at least)
observable.

2021-10-01  Jakub Jelinek  <jakub@redhat.com>

gcc/
* tree.h (OMP_CLAUSE_ORDER_REPRODUCIBLE): Define.
* tree-pretty-print.c (dump_omp_clause) <case OMP_CLAUSE_ORDER>: Print
reproducible: for OMP_CLAUSE_ORDER_REPRODUCIBLE.
* omp-general.c (omp_extract_for_data): If OMP_CLAUSE_ORDER is seen
without OMP_CLAUSE_ORDER_UNCONSTRAINED, overwrite sched_kind to
OMP_CLAUSE_SCHEDULE_STATIC.
gcc/c-family/
* c-omp.c (c_omp_split_clauses): Also copy
OMP_CLAUSE_ORDER_REPRODUCIBLE.
gcc/c/
* c-parser.c (c_parser_omp_clause_order): Set
OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
gcc/cp/
* parser.c (cp_parser_omp_clause_order): Set
OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
gcc/fortran/
* gfortran.h (gfc_omp_clauses): Add order_reproducible bitfield.
* dump-parse-tree.c (show_omp_clauses): Print REPRODUCIBLE: for it.
* openmp.c (gfc_match_omp_clauses): Set order_reproducible for
explicit reproducible: modifier.
* trans-openmp.c (gfc_trans_omp_clauses): Set
OMP_CLAUSE_ORDER_REPRODUCIBLE for order_reproducible.
(gfc_split_omp_clauses): Also copy order_reproducible.
gcc/testsuite/
* gfortran.dg/gomp/order-5.f90: Adjust scan-tree-dump-times regexps.
libgomp/
* testsuite/libgomp.c-c++-common/order-reproducible-1.c: New test.
* testsuite/libgomp.c-c++-common/order-reproducible-2.c: New test.

(cherry picked from commit e705b8533aa0a00a65734eb5fd6344295723dccc)

20 files changed:
gcc/ChangeLog.omp
gcc/c-family/ChangeLog.omp
gcc/c-family/c-omp.c
gcc/c/ChangeLog.omp
gcc/c/c-parser.c
gcc/cp/ChangeLog.omp
gcc/cp/parser.c
gcc/fortran/ChangeLog.omp
gcc/fortran/dump-parse-tree.c
gcc/fortran/gfortran.h
gcc/fortran/openmp.c
gcc/fortran/trans-openmp.c
gcc/omp-general.c
gcc/testsuite/ChangeLog.omp
gcc/testsuite/gfortran.dg/gomp/order-5.f90
gcc/tree-pretty-print.c
gcc/tree.h
libgomp/ChangeLog.omp
libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c [new file with mode: 0644]

index ec76feb2829425dd01e1928964fb071760d0ec59..c69454167c0acf771b95c7b06638ee61459ffbcf 100644 (file)
@@ -1,3 +1,15 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree.h (OMP_CLAUSE_ORDER_REPRODUCIBLE): Define.
+       * tree-pretty-print.c (dump_omp_clause) <case OMP_CLAUSE_ORDER>: Print
+       reproducible: for OMP_CLAUSE_ORDER_REPRODUCIBLE.
+       * omp-general.c (omp_extract_for_data): If OMP_CLAUSE_ORDER is seen
+       without OMP_CLAUSE_ORDER_UNCONSTRAINED, overwrite sched_kind to
+       OMP_CLAUSE_SCHEDULE_STATIC.
+
 2021-09-30  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 7a8616e7ee6a48d8f453c95a5041d78c58db1307..afb871f6d82a13f365aa2c78160c15282de3707f 100644 (file)
@@ -1,3 +1,11 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-omp.c (c_omp_split_clauses): Also copy
+       OMP_CLAUSE_ORDER_REPRODUCIBLE.
+
 2021-09-22  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 5669718a0bd340319622acb0cceaf6152fbe55b7..fa07738b7455ed16accc349054b2dc96652fc48e 100644 (file)
@@ -2273,6 +2273,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;
            }
@@ -2284,6 +2286,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;
index 434d5adeb66149b38dbf87210309510225264ed6..bd47ba3160ffe17fff86e5f6ca6f03aedb9bbea5 100644 (file)
@@ -1,3 +1,11 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.c (c_parser_omp_clause_order): Set
+       OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
 2021-09-22  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index ebec1305f79bd12c0455bd5c9bc2bdc3d4aacb10..367fb2fc04bf7c6fc9e77d83263a902732032b03 100644 (file)
@@ -14642,6 +14642,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))
@@ -14652,7 +14653,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%>");
@@ -14677,6 +14680,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;
 
index f75271fcccb1b3b0130a9cb3e8aa84bc2c3cc0ab..06b5dc933026b0443918cfc07253cd165e54c3be 100644 (file)
@@ -1,3 +1,11 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * parser.c (cp_parser_omp_clause_order): Set
+       OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
 2021-09-23  Tobias Burnus  <tobias@codesourcery.com>
 
        2021-09-23  Jakub Jelinek  <jakub@redhat.com>
index 58d4625dbf9f5b9a8c1cdea8b84f1aea5ece4a25..954f85d4b2d5227a28ca70407bc6ed65a3166f84 100644 (file)
@@ -37500,6 +37500,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))
@@ -37512,7 +37513,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%>");
@@ -37543,6 +37546,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;
 
index 9a1995ba8f10f2e3828ac1bcc8d5ac0221e7c02c..3e65e177e7559f62748454eef73ba284816da417 100644 (file)
@@ -1,3 +1,16 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * gfortran.h (gfc_omp_clauses): Add order_reproducible bitfield.
+       * dump-parse-tree.c (show_omp_clauses): Print REPRODUCIBLE: for it.
+       * openmp.c (gfc_match_omp_clauses): Set order_reproducible for
+       explicit reproducible: modifier.
+       * trans-openmp.c (gfc_trans_omp_clauses): Set
+       OMP_CLAUSE_ORDER_REPRODUCIBLE for order_reproducible.
+       (gfc_split_omp_clauses): Also copy order_reproducible.
+
 2021-09-30  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 61b6dbe4fad0e1ca613867f1f265be4ea2e1553f..f7b74f78e46384c7005a3f3a997acbb99d9a42aa 100644 (file)
@@ -1632,6 +1632,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)
index 48e20811b35154c5e251cc8728d9c83e0f527fdb..be11da62d2a6171f464ea2bf561ff4487d47c9cd 100644 (file)
@@ -1493,8 +1493,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;
index 44bfdfe68f271d0e2337c53f8f90484d5204302d..0cf9872bf7a7db7016f093252b09aad886297bd5 100644 (file)
@@ -2388,8 +2388,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;
index 0ad87fd1539e4d24eb3966b80ed5cea968acd662..5d2b9916893ecd607f5226725f9971159853f2e5 100644 (file)
@@ -3829,6 +3829,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);
     }
 
@@ -5932,6 +5933,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)
        {
@@ -5988,6 +5991,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)
        {
@@ -6006,6 +6011,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;
index b9cd78bdeb052663d68b033bf9e5f3d9dfbce071..127e68792583bef86ef144627002231ac984952a 100644 (file)
@@ -192,6 +192,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;
@@ -276,10 +277,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
index 9991a6ed0dd30e2e0da894c6473c7c63a521c29e..ecf2ed8adfdb09df6625ff03a22e738d740f4c6f 100644 (file)
@@ -1,3 +1,10 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * gfortran.dg/gomp/order-5.f90: Adjust scan-tree-dump-times regexps.
+
 2021-09-30  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 4d9e33642afb569be801af6f3f45fc10a5ca40b4..0dddb968cb4ef2ced48e1803d503b705fa572c0a 100644 (file)
@@ -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"} }
index 163566beaaa8ce3f14a622ce44b63084b32701c6..d769cd8f07c5f0da1b23ff84019a39ffc0673e0c 100644 (file)
@@ -1216,6 +1216,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;
 
index f8853dfb7506dd1321ce9b716dd7755aa19bd967..cc7716f5007b7bd8f5d5af45d2007ad0a9306269 100644 (file)
@@ -1728,6 +1728,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, \
index cd59b5ed378c720eb0381c5b65d8616fef7584b7..6606f50f3cb26dac993e35b15adc5e67e616662d 100644 (file)
@@ -1,3 +1,11 @@
+2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * testsuite/libgomp.c-c++-common/order-reproducible-1.c: New test.
+       * testsuite/libgomp.c-c++-common/order-reproducible-2.c: New test.
+
 2021-10-01  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
diff --git a/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c b/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c
new file mode 100644 (file)
index 0000000..7e6968f
--- /dev/null
@@ -0,0 +1,63 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  int a[128];
+  #pragma omp teams num_teams(5)
+  {
+    #pragma omp loop bind(teams)
+    for (int i = 0; i < 128; i++)
+      {
+       a[i] = i;
+       if (i == 0)
+         usleep (20);
+       else if (i == 17)
+         usleep (40);
+      }
+    #pragma omp loop bind(teams)
+    for (int i = 0; i < 128; i++)
+      a[i] += i;
+  }
+  for (int i = 0; i < 128; i++)
+    if (a[i] != 2 * i)
+      abort ();
+  #pragma omp teams num_teams(5)
+  {
+    #pragma omp loop bind(teams) order(concurrent)
+    for (int i = 0; i < 128; i++)
+      {
+       a[i] *= 2;
+       if (i == 1)
+         usleep (20);
+       else if (i == 13)
+         usleep (40);
+      }
+    #pragma omp loop bind(teams) order(concurrent)
+    for (int i = 0; i < 128; i++)
+      a[i] += i;
+  }
+  for (int i = 0; i < 128; i++)
+    if (a[i] != 5 * i)
+      abort ();
+  #pragma omp teams num_teams(5)
+  {
+    #pragma omp loop bind(teams) order(reproducible:concurrent)
+    for (int i = 0; i < 128; i++)
+      {
+       a[i] *= 2;
+       if (i == 2)
+         usleep (20);
+       else if (i == 105)
+         usleep (40);
+      }
+    #pragma omp loop bind(teams) order(reproducible:concurrent)
+    for (int i = 0; i < 128; i++)
+      a[i] += i;
+  }
+  for (int i = 0; i < 128; i++)
+    if (a[i] != 11 * i)
+      abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c b/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c
new file mode 100644 (file)
index 0000000..c8ba658
--- /dev/null
@@ -0,0 +1,28 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  int a[128];
+  #pragma omp parallel num_threads(8)
+  {
+    #pragma omp barrier
+    #pragma omp for nowait schedule (dynamic, 2) order(reproducible:concurrent)
+    for (int i = 0; i < 128; i++)
+      {
+       a[i] = i;
+       if (i == 0)
+         usleep (20);
+       else if (i == 17)
+         usleep (40);
+      }
+    #pragma omp for nowait schedule (dynamic, 2) order(reproducible:concurrent)
+    for (int i = 0; i < 128; i++)
+      a[i] += i;
+  }
+  for (int i = 0; i < 128; i++)
+    if (a[i] != 2 * i)
+      abort ();
+  return 0;
+}