Hi all, hi Jakub,

On 12.08.21 22:48, Jakub Jelinek via Gcc-patches wrote:
This construct has been introduced as a replacement for master
construct, but unlike that construct is slightly more general,
has an optional clause which allows to choose which thread
will be the one running the region, it can be some other thread
than the master (primary) thread with number 0, or it could be no
threads or multiple threads (then of course one needs to be careful
about data races).

And the attached patch extends this to Fortran.

When converting the C/C++ runtime testcase to Fortran, I did run into a bug:

https://gcc.gnu.org/PR101899 (see PR or testcase; related to 'omp
taskloop'.)

Tobias

-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
Fortran/OpenMP: Add support for OpenMP 5.1 masked construct

Commit r12-2891-gd0befed793b94f3f407be44e6f69f81a02f5f073 added C/C++
support for the masked construct. This patch extends it to
Fortran.

gcc/fortran/ChangeLog:

	* dump-parse-tree.c (show_omp_clauses): Handle 'filter' clause.
	(show_omp_node, show_code_node): Handle (combined) omp masked construct.
	* frontend-passes.c (gfc_code_walker): Likewise.
	* gfortran.h (enum gfc_statement): Add ST_OMP_*_MASKED*.
	(enum gfc_exec_op): Add EXEC_OMP_*_MASKED*.
	* match.h (gfc_match_omp_masked, gfc_match_omp_masked_taskloop,
	gfc_match_omp_masked_taskloop_simd, gfc_match_omp_parallel_masked,
	gfc_match_omp_parallel_masked_taskloop,
	gfc_match_omp_parallel_masked_taskloop_simd): New prototypes.
	* openmp.c (enum omp_mask1): Add OMP_CLAUSE_FILTER.
	(gfc_match_omp_clauses): Match it.
	(OMP_MASKED_CLAUSES, gfc_match_omp_parallel_masked,
	gfc_match_omp_parallel_masked_taskloop,
	gfc_match_omp_parallel_masked_taskloop_simd,
	gfc_match_omp_masked, gfc_match_omp_masked_taskloop,
	gfc_match_omp_masked_taskloop_simd): New.
	(resolve_omp_clauses): Resolve filter clause. 
	(gfc_resolve_omp_parallel_blocks, resolve_omp_do,
	omp_code_to_statement, gfc_resolve_omp_directive): Handle
	omp masked constructs.
	* parse.c (decode_omp_directive, case_exec_markers,
	gfc_ascii_statement, parse_omp_do, parse_omp_structured_block,
	parse_executable): Likewise.
	* resolve.c (gfc_resolve_blocks, gfc_resolve_code): Likewise.
	* st.c (gfc_free_statement): Likewise.
	* trans-openmp.c (gfc_trans_omp_clauses): Handle filter clause.
	(GFC_OMP_SPLIT_MASKED, GFC_OMP_MASK_MASKED): New enum values.
	(gfc_trans_omp_masked): New.
	(gfc_split_omp_clauses): Handle combined masked directives.
	(gfc_trans_omp_master_taskloop): Rename to ...
	(gfc_trans_omp_master_masked_taskloop): ... this; handle also
	combined masked directives.
	(gfc_trans_omp_parallel_master): Rename to ...
	(gfc_trans_omp_parallel_master_masked): ... this; handle
	combined masked directives.
	(gfc_trans_omp_directive): Handle EXEC_OMP_*_MASKED*.
	* trans.c (trans_code): Likewise.

libgomp/ChangeLog:

	* testsuite/libgomp.fortran/masked-1.f90: New test.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/masked-1.f90: New test.
	* gfortran.dg/gomp/masked-2.f90: New test.
	* gfortran.dg/gomp/masked-3.f90: New test.
	* gfortran.dg/gomp/masked-combined-1.f90: New test.
	* gfortran.dg/gomp/masked-combined-2.f90: New test.

 gcc/fortran/dump-parse-tree.c                      |  24 +++
 gcc/fortran/frontend-passes.c                      |   3 +
 gcc/fortran/gfortran.h                             |  14 +-
 gcc/fortran/match.h                                |   6 +
 gcc/fortran/openmp.c                               |  98 ++++++++++++
 gcc/fortran/parse.c                                |  91 ++++++++++-
 gcc/fortran/resolve.c                              |  15 ++
 gcc/fortran/st.c                                   |   6 +
 gcc/fortran/trans-openmp.c                         | 176 +++++++++++++++++----
 gcc/fortran/trans.c                                |   6 +
 gcc/testsuite/gfortran.dg/gomp/masked-1.f90        |  94 +++++++++++
 gcc/testsuite/gfortran.dg/gomp/masked-2.f90        |  46 ++++++
 gcc/testsuite/gfortran.dg/gomp/masked-3.f90        |  12 ++
 .../gfortran.dg/gomp/masked-combined-1.f90         |  65 ++++++++
 .../gfortran.dg/gomp/masked-combined-2.f90         |  24 +++
 libgomp/testsuite/libgomp.fortran/masked-1.f90     | 141 +++++++++++++++++
 16 files changed, 788 insertions(+), 33 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 360abf18a6a..53c49fe4d6f 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1808,6 +1808,12 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
       show_expr (omp_clauses->grainsize);
       fputc (')', dumpfile);
     }
+  if (omp_clauses->filter)
+    {
+      fputs (" FILTER(", dumpfile);
+      show_expr (omp_clauses->filter);
+      fputc (')', dumpfile);
+    }
   if (omp_clauses->hint)
     {
       fputs (" HINT(", dumpfile);
@@ -1946,6 +1952,9 @@ show_omp_node (int level, gfc_code *c)
     case EXEC_OMP_DO_SIMD: name = "DO SIMD"; break;
     case EXEC_OMP_LOOP: name = "LOOP"; break;
     case EXEC_OMP_FLUSH: name = "FLUSH"; break;
+    case EXEC_OMP_MASKED: name = "MASKED"; break;
+    case EXEC_OMP_MASKED_TASKLOOP: name = "MASKED TASKLOOP"; break;
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD: name = "MASKED TASKLOOP SIMD"; break;
     case EXEC_OMP_MASTER: name = "MASTER"; break;
     case EXEC_OMP_MASTER_TASKLOOP: name = "MASTER TASKLOOP"; break;
     case EXEC_OMP_MASTER_TASKLOOP_SIMD: name = "MASTER TASKLOOP SIMD"; break;
@@ -1956,6 +1965,11 @@ show_omp_node (int level, gfc_code *c)
     case EXEC_OMP_PARALLEL_DO_SIMD: name = "PARALLEL DO SIMD"; break;
     case EXEC_OMP_PARALLEL_LOOP: name = "PARALLEL LOOP"; break;
     case EXEC_OMP_PARALLEL_MASTER: name = "PARALLEL MASTER"; break;
+    case EXEC_OMP_PARALLEL_MASKED: name = "PARALLEL MASK"; break;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+      name = "PARALLEL MASK TASKLOOP"; break;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+      name = "PARALLEL MASK TASKLOOP SIMD"; break;
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
       name = "PARALLEL MASTER TASKLOOP"; break;
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
@@ -2032,10 +2046,14 @@ show_omp_node (int level, gfc_code *c)
     case EXEC_OMP_DO_SIMD:
     case EXEC_OMP_LOOP:
     case EXEC_OMP_ORDERED:
+    case EXEC_OMP_MASKED:
     case EXEC_OMP_PARALLEL:
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_LOOP:
+    case EXEC_OMP_PARALLEL_MASKED:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
@@ -3250,6 +3268,9 @@ show_code_node (int level, gfc_code *c)
     case EXEC_OMP_DO_SIMD:
     case EXEC_OMP_FLUSH:
     case EXEC_OMP_LOOP:
+    case EXEC_OMP_MASKED:
+    case EXEC_OMP_MASKED_TASKLOOP:
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_MASTER:
     case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
@@ -3258,6 +3279,9 @@ show_code_node (int level, gfc_code *c)
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_LOOP:
+    case EXEC_OMP_PARALLEL_MASKED:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 996dcc2e547..145bff50f3e 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -5556,6 +5556,9 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
 	    case EXEC_OMP_PARALLEL_DO:
 	    case EXEC_OMP_PARALLEL_DO_SIMD:
 	    case EXEC_OMP_PARALLEL_LOOP:
+	    case EXEC_OMP_PARALLEL_MASKED:
+	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	    case EXEC_OMP_PARALLEL_MASTER:
 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 8f75dd95394..5fde4174a5b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -275,7 +275,13 @@ enum gfc_statement
   ST_OMP_PARALLEL_LOOP, ST_OMP_END_PARALLEL_LOOP, ST_OMP_TEAMS_LOOP,
   ST_OMP_END_TEAMS_LOOP, ST_OMP_TARGET_PARALLEL_LOOP,
   ST_OMP_END_TARGET_PARALLEL_LOOP, ST_OMP_TARGET_TEAMS_LOOP,
-  ST_OMP_END_TARGET_TEAMS_LOOP, ST_NONE
+  ST_OMP_END_TARGET_TEAMS_LOOP, ST_OMP_MASKED, ST_OMP_END_MASKED,
+  ST_OMP_PARALLEL_MASKED, ST_OMP_END_PARALLEL_MASKED,
+  ST_OMP_PARALLEL_MASKED_TASKLOOP, ST_OMP_END_PARALLEL_MASKED_TASKLOOP,
+  ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
+  ST_OMP_END_PARALLEL_MASKED_TASKLOOP_SIMD, ST_OMP_MASKED_TASKLOOP,
+  ST_OMP_END_MASKED_TASKLOOP, ST_OMP_MASKED_TASKLOOP_SIMD,
+  ST_OMP_END_MASKED_TASKLOOP_SIMD, ST_NONE
 };
 
 /* Types of interfaces that we can have.  Assignment interfaces are
@@ -1466,6 +1472,7 @@ typedef struct gfc_omp_clauses
   struct gfc_expr *device;
   struct gfc_expr *thread_limit;
   struct gfc_expr *grainsize;
+  struct gfc_expr *filter;
   struct gfc_expr *hint;
   struct gfc_expr *num_tasks;
   struct gfc_expr *priority;
@@ -2758,7 +2765,10 @@ enum gfc_exec_op
   EXEC_OMP_PARALLEL_MASTER, EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
   EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD, EXEC_OMP_MASTER_TASKLOOP,
   EXEC_OMP_MASTER_TASKLOOP_SIMD, EXEC_OMP_LOOP, EXEC_OMP_PARALLEL_LOOP,
-  EXEC_OMP_TEAMS_LOOP, EXEC_OMP_TARGET_PARALLEL_LOOP, EXEC_OMP_TARGET_TEAMS_LOOP
+  EXEC_OMP_TEAMS_LOOP, EXEC_OMP_TARGET_PARALLEL_LOOP,
+  EXEC_OMP_TARGET_TEAMS_LOOP, EXEC_OMP_MASKED, EXEC_OMP_PARALLEL_MASKED,
+  EXEC_OMP_PARALLEL_MASKED_TASKLOOP, EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
+  EXEC_OMP_MASKED_TASKLOOP, EXEC_OMP_MASKED_TASKLOOP_SIMD
 };
 
 typedef struct gfc_code
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index bb1f34fc444..dce650346d3 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -169,6 +169,9 @@ match gfc_match_omp_do (void);
 match gfc_match_omp_do_simd (void);
 match gfc_match_omp_loop (void);
 match gfc_match_omp_flush (void);
+match gfc_match_omp_masked (void);
+match gfc_match_omp_masked_taskloop (void);
+match gfc_match_omp_masked_taskloop_simd (void);
 match gfc_match_omp_master (void);
 match gfc_match_omp_master_taskloop (void);
 match gfc_match_omp_master_taskloop_simd (void);
@@ -178,6 +181,9 @@ match gfc_match_omp_parallel (void);
 match gfc_match_omp_parallel_do (void);
 match gfc_match_omp_parallel_do_simd (void);
 match gfc_match_omp_parallel_loop (void);
+match gfc_match_omp_parallel_masked (void);
+match gfc_match_omp_parallel_masked_taskloop (void);
+match gfc_match_omp_parallel_masked_taskloop_simd (void);
 match gfc_match_omp_parallel_master (void);
 match gfc_match_omp_parallel_master_taskloop (void);
 match gfc_match_omp_parallel_master_taskloop_simd (void);
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index ec558656602..1bce43cb33e 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -847,6 +847,7 @@ enum omp_mask1
   OMP_CLAUSE_DETACH,  /* OpenMP 5.0.  */
   OMP_CLAUSE_AFFINITY,  /* OpenMP 5.0.  */
   OMP_CLAUSE_BIND,  /* OpenMP 5.0.  */
+  OMP_CLAUSE_FILTER,  /* OpenMP 5.1.  */
   OMP_CLAUSE_NOWAIT,
   /* This must come last.  */
   OMP_MASK1_LAST
@@ -1772,6 +1773,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  break;
 	case 'f':
+	  if ((mask & OMP_CLAUSE_FILTER)
+	      && c->filter == NULL
+	      && gfc_match ("filter ( %e )", &c->filter) == MATCH_YES)
+	    continue;
 	  if ((mask & OMP_CLAUSE_FINAL)
 	      && c->final_expr == NULL
 	      && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
@@ -3199,6 +3204,8 @@ cleanup:
 #define OMP_ATOMIC_CLAUSES \
   (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT	\
    | OMP_CLAUSE_MEMORDER)
+#define OMP_MASKED_CLAUSES \
+  (omp_mask (OMP_CLAUSE_FILTER))
 
 
 static match
@@ -4157,6 +4164,31 @@ gfc_match_omp_parallel_do_simd (void)
 }
 
 
+match
+gfc_match_omp_parallel_masked (void)
+{
+  return match_omp (EXEC_OMP_PARALLEL_MASKED,
+		    OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
+}
+
+match
+gfc_match_omp_parallel_masked_taskloop (void)
+{
+  return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
+		    (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
+		     | OMP_TASKLOOP_CLAUSES)
+		    & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
+}
+
+match
+gfc_match_omp_parallel_masked_taskloop_simd (void)
+{
+  return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
+		    (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
+		     | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
+		    & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
+}
+
 match
 gfc_match_omp_parallel_master (void)
 {
@@ -4703,6 +4735,27 @@ gfc_match_omp_workshare (void)
 }
 
 
+match
+gfc_match_omp_masked (void)
+{
+  return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
+}
+
+match
+gfc_match_omp_masked_taskloop (void)
+{
+  return match_omp (EXEC_OMP_MASKED_TASKLOOP,
+		    OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
+}
+
+match
+gfc_match_omp_masked_taskloop_simd (void)
+{
+  return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
+		    (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
+		     | OMP_SIMD_CLAUSES));
+}
+
 match
 gfc_match_omp_master (void)
 {
@@ -5254,6 +5307,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 
 	    case EXEC_OMP_PARALLEL:
 	    case EXEC_OMP_PARALLEL_DO:
+	    case EXEC_OMP_PARALLEL_MASKED:
 	    case EXEC_OMP_PARALLEL_MASTER:
 	    case EXEC_OMP_PARALLEL_SECTIONS:
 	    case EXEC_OMP_PARALLEL_WORKSHARE:
@@ -5268,10 +5322,12 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	      ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
 	      break;
 
+	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
 	      ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
 	      break;
 
+	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
 	      ok = (ifc == OMP_IF_PARALLEL
 		    || ifc == OMP_IF_TASKLOOP
@@ -5290,11 +5346,13 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	      break;
 
 	    case EXEC_OMP_TASKLOOP:
+	    case EXEC_OMP_MASKED_TASKLOOP:
 	    case EXEC_OMP_MASTER_TASKLOOP:
 	      ok = ifc == OMP_IF_TASKLOOP;
 	      break;
 
 	    case EXEC_OMP_TASKLOOP_SIMD:
+	    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
 	    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
 	      ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
 	      break;
@@ -6060,9 +6118,13 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 			&& (code->op == EXEC_OMP_LOOP
 			    || code->op == EXEC_OMP_TASKLOOP
 			    || code->op == EXEC_OMP_TASKLOOP_SIMD
+			    || code->op == EXEC_OMP_MASKED_TASKLOOP
+			    || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
 			    || code->op == EXEC_OMP_MASTER_TASKLOOP
 			    || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
 			    || code->op == EXEC_OMP_PARALLEL_LOOP
+			    || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
+			    || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
 			    || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
 			    || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
 			    || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
@@ -6322,6 +6384,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
     resolve_positive_int_expr (omp_clauses->num_teams, "NUM_TEAMS");
   if (omp_clauses->device)
     resolve_nonnegative_int_expr (omp_clauses->device, "DEVICE");
+  if (omp_clauses->filter)
+    resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
   if (omp_clauses->hint)
     {
       resolve_scalar_int_expr (omp_clauses->hint, "HINT");
@@ -6984,8 +7048,12 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+    case EXEC_OMP_MASKED_TASKLOOP:
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_TARGET_PARALLEL_DO:
@@ -7133,6 +7201,13 @@ resolve_omp_do (gfc_code *code)
       is_simd = true;
       break;
     case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+      name = "!$OMP PARALLEL MASKED TASKLOOP";
+      break;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+      name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
+      is_simd = true;
+      break;
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
       name = "!$OMP PARALLEL MASTER TASKLOOP";
       break;
@@ -7140,6 +7215,11 @@ resolve_omp_do (gfc_code *code)
       name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
       is_simd = true;
       break;
+    case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
+      name = "!$OMP MASKED TASKLOOP SIMD";
+      is_simd = true;
+      break;
     case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
       name = "!$OMP MASTER TASKLOOP SIMD";
@@ -7302,6 +7382,12 @@ omp_code_to_statement (gfc_code *code)
     {
     case EXEC_OMP_PARALLEL:
       return ST_OMP_PARALLEL;
+    case EXEC_OMP_PARALLEL_MASKED:
+      return ST_OMP_PARALLEL_MASKED;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+      return ST_OMP_PARALLEL_MASKED_TASKLOOP;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+      return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
     case EXEC_OMP_PARALLEL_MASTER:
       return ST_OMP_PARALLEL_MASTER;
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
@@ -7316,6 +7402,12 @@ omp_code_to_statement (gfc_code *code)
       return ST_OMP_ORDERED;
     case EXEC_OMP_CRITICAL:
       return ST_OMP_CRITICAL;
+    case EXEC_OMP_MASKED:
+      return ST_OMP_MASKED;
+    case EXEC_OMP_MASKED_TASKLOOP:
+      return ST_OMP_MASKED_TASKLOOP;
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
+      return ST_OMP_MASKED_TASKLOOP_SIMD;
     case EXEC_OMP_MASTER:
       return ST_OMP_MASTER;
     case EXEC_OMP_MASTER_TASKLOOP:
@@ -7822,8 +7914,12 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_LOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+    case EXEC_OMP_MASKED_TASKLOOP:
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_SIMD:
@@ -7846,8 +7942,10 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
       resolve_omp_do (code);
       break;
     case EXEC_OMP_CANCEL:
+    case EXEC_OMP_MASKED:
     case EXEC_OMP_PARALLEL_WORKSHARE:
     case EXEC_OMP_PARALLEL:
+    case EXEC_OMP_PARALLEL_MASKED:
     case EXEC_OMP_PARALLEL_MASTER:
     case EXEC_OMP_PARALLEL_SECTIONS:
     case EXEC_OMP_SECTIONS:
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 6d7845e8517..e1d78de5d9e 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -920,6 +920,11 @@ decode_omp_directive (void)
       matchs ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD);
       matcho ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
       matchs ("end simd", gfc_match_omp_eos_error, ST_OMP_END_SIMD);
+      matcho ("end masked taskloop simd", gfc_match_omp_eos_error,
+	      ST_OMP_END_MASKED_TASKLOOP_SIMD);
+      matcho ("end masked taskloop", gfc_match_omp_eos_error,
+	      ST_OMP_END_MASKED_TASKLOOP);
+      matcho ("end masked", gfc_match_omp_eos_error, ST_OMP_END_MASKED);
       matcho ("end master taskloop simd", gfc_match_omp_eos_error,
 	      ST_OMP_END_MASTER_TASKLOOP_SIMD);
       matcho ("end master taskloop", gfc_match_omp_eos_error,
@@ -929,6 +934,12 @@ decode_omp_directive (void)
       matchs ("end parallel do simd", gfc_match_omp_eos_error,
 	      ST_OMP_END_PARALLEL_DO_SIMD);
       matcho ("end parallel do", gfc_match_omp_eos_error, ST_OMP_END_PARALLEL_DO);
+      matcho ("end parallel masked taskloop simd", gfc_match_omp_eos_error,
+	      ST_OMP_END_PARALLEL_MASKED_TASKLOOP_SIMD);
+      matcho ("end parallel masked taskloop", gfc_match_omp_eos_error,
+	      ST_OMP_END_PARALLEL_MASKED_TASKLOOP);
+      matcho ("end parallel masked", gfc_match_omp_eos_error,
+	      ST_OMP_END_PARALLEL_MASKED);
       matcho ("end parallel master taskloop simd", gfc_match_omp_eos_error,
 	      ST_OMP_END_PARALLEL_MASTER_TASKLOOP_SIMD);
       matcho ("end parallel master taskloop", gfc_match_omp_eos_error,
@@ -982,6 +993,11 @@ decode_omp_directive (void)
       matcho ("flush", gfc_match_omp_flush, ST_OMP_FLUSH);
       break;
     case 'm':
+      matcho ("masked taskloop simd", gfc_match_omp_masked_taskloop_simd,
+	      ST_OMP_MASKED_TASKLOOP_SIMD);
+      matcho ("masked taskloop", gfc_match_omp_masked_taskloop,
+	      ST_OMP_MASKED_TASKLOOP);
+      matcho ("masked", gfc_match_omp_masked, ST_OMP_MASKED);
       matcho ("master taskloop simd", gfc_match_omp_master_taskloop_simd,
 	      ST_OMP_MASTER_TASKLOOP_SIMD);
       matcho ("master taskloop", gfc_match_omp_master_taskloop,
@@ -1009,6 +1025,14 @@ decode_omp_directive (void)
       matcho ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO);
       matcho ("parallel loop", gfc_match_omp_parallel_loop,
 	      ST_OMP_PARALLEL_LOOP);
+      matcho ("parallel masked taskloop simd",
+	      gfc_match_omp_parallel_masked_taskloop_simd,
+	      ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD);
+      matcho ("parallel masked taskloop",
+	      gfc_match_omp_parallel_masked_taskloop,
+	      ST_OMP_PARALLEL_MASKED_TASKLOOP);
+      matcho ("parallel masked", gfc_match_omp_parallel_masked,
+	      ST_OMP_PARALLEL_MASKED);
       matcho ("parallel master taskloop simd",
 	      gfc_match_omp_parallel_master_taskloop_simd,
 	      ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD);
@@ -1639,11 +1663,15 @@ next_statement (void)
 #define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \
   case ST_IF_BLOCK: case ST_BLOCK: case ST_ASSOCIATE: \
   case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_SELECT_TYPE: \
-  case ST_SELECT_RANK: case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASTER: \
+  case ST_SELECT_RANK: case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASKED: \
+  case ST_OMP_PARALLEL_MASKED_TASKLOOP: \
+  case ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: case ST_OMP_PARALLEL_MASTER: \
   case ST_OMP_PARALLEL_MASTER_TASKLOOP: \
   case ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: \
   case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \
-  case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_MASTER_TASKLOOP: \
+  case ST_OMP_CRITICAL: case ST_OMP_MASKED: case ST_OMP_MASKED_TASKLOOP: \
+  case ST_OMP_MASKED_TASKLOOP_SIMD: \
+  case ST_OMP_MASTER: case ST_OMP_MASTER_TASKLOOP: \
   case ST_OMP_MASTER_TASKLOOP_SIMD: case ST_OMP_SINGLE: \
   case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \
   case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: \
@@ -2376,6 +2404,15 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_END_LOOP:
       p = "!$OMP END LOOP";
       break;
+    case ST_OMP_END_MASKED:
+      p = "!$OMP END MASKED";
+      break;
+    case ST_OMP_END_MASKED_TASKLOOP:
+      p = "!$OMP END MASKED TASKLOOP";
+      break;
+    case ST_OMP_END_MASKED_TASKLOOP_SIMD:
+      p = "!$OMP END MASKED TASKLOOP SIMD";
+      break;
     case ST_OMP_END_MASTER:
       p = "!$OMP END MASTER";
       break;
@@ -2400,6 +2437,15 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_END_PARALLEL_LOOP:
       p = "!$OMP END PARALLEL LOOP";
       break;
+    case ST_OMP_END_PARALLEL_MASKED:
+      p = "!$OMP END PARALLEL MASKED";
+      break;
+    case ST_OMP_END_PARALLEL_MASKED_TASKLOOP:
+      p = "!$OMP END PARALLEL MASKED TASKLOOP";
+      break;
+    case ST_OMP_END_PARALLEL_MASKED_TASKLOOP_SIMD:
+      p = "!$OMP END PARALLEL MASKED TASKLOOP SIMD";
+      break;
     case ST_OMP_END_PARALLEL_MASTER:
       p = "!$OMP END PARALLEL MASTER";
       break;
@@ -2499,6 +2545,15 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_LOOP:
       p = "!$OMP LOOP";
       break;
+    case ST_OMP_MASKED:
+      p = "!$OMP MASKED";
+      break;
+    case ST_OMP_MASKED_TASKLOOP:
+      p = "!$OMP MASKED TASKLOOP";
+      break;
+    case ST_OMP_MASKED_TASKLOOP_SIMD:
+      p = "!$OMP MASKED TASKLOOP SIMD";
+      break;
     case ST_OMP_MASTER:
       p = "!$OMP MASTER";
       break;
@@ -2524,6 +2579,15 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_PARALLEL_DO_SIMD:
       p = "!$OMP PARALLEL DO SIMD";
       break;
+    case ST_OMP_PARALLEL_MASKED:
+      p = "!$OMP PARALLEL MASKED";
+      break;
+    case ST_OMP_PARALLEL_MASKED_TASKLOOP:
+      p = "!$OMP PARALLEL MASKED TASKLOOP";
+      break;
+    case ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+      p = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
+      break;
     case ST_OMP_PARALLEL_MASTER:
       p = "!$OMP PARALLEL MASTER";
       break;
@@ -5127,10 +5191,20 @@ parse_omp_do (gfc_statement omp_st)
       break;
     case ST_OMP_TASKLOOP: omp_end_st = ST_OMP_END_TASKLOOP; break;
     case ST_OMP_TASKLOOP_SIMD: omp_end_st = ST_OMP_END_TASKLOOP_SIMD; break;
+    case ST_OMP_MASKED_TASKLOOP: omp_end_st = ST_OMP_END_MASKED_TASKLOOP; break;
+    case ST_OMP_MASKED_TASKLOOP_SIMD:
+      omp_end_st = ST_OMP_END_MASKED_TASKLOOP_SIMD;
+      break;
     case ST_OMP_MASTER_TASKLOOP: omp_end_st = ST_OMP_END_MASTER_TASKLOOP; break;
     case ST_OMP_MASTER_TASKLOOP_SIMD:
       omp_end_st = ST_OMP_END_MASTER_TASKLOOP_SIMD;
       break;
+    case ST_OMP_PARALLEL_MASKED_TASKLOOP:
+      omp_end_st = ST_OMP_END_PARALLEL_MASKED_TASKLOOP;
+      break;
+    case ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+      omp_end_st = ST_OMP_END_PARALLEL_MASKED_TASKLOOP_SIMD;
+      break;
     case ST_OMP_PARALLEL_MASTER_TASKLOOP:
       omp_end_st = ST_OMP_END_PARALLEL_MASTER_TASKLOOP;
       break;
@@ -5380,6 +5454,9 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
     case ST_OMP_PARALLEL:
       omp_end_st = ST_OMP_END_PARALLEL;
       break;
+    case ST_OMP_PARALLEL_MASKED:
+      omp_end_st = ST_OMP_END_PARALLEL_MASKED;
+      break;
     case ST_OMP_PARALLEL_MASTER:
       omp_end_st = ST_OMP_END_PARALLEL_MASTER;
       break;
@@ -5395,6 +5472,9 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
     case ST_OMP_CRITICAL:
       omp_end_st = ST_OMP_END_CRITICAL;
       break;
+    case ST_OMP_MASKED:
+      omp_end_st = ST_OMP_END_MASKED;
+      break;
     case ST_OMP_MASTER:
       omp_end_st = ST_OMP_END_MASTER;
       break;
@@ -5477,6 +5557,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
 		  break;
 
 		case ST_OMP_PARALLEL:
+		case ST_OMP_PARALLEL_MASKED:
 		case ST_OMP_PARALLEL_MASTER:
 		case ST_OMP_PARALLEL_SECTIONS:
 		  parse_omp_structured_block (st, false);
@@ -5679,11 +5760,13 @@ parse_executable (gfc_statement st)
 	  break;
 
 	case ST_OMP_PARALLEL:
+	case ST_OMP_PARALLEL_MASKED:
 	case ST_OMP_PARALLEL_MASTER:
 	case ST_OMP_PARALLEL_SECTIONS:
 	case ST_OMP_SECTIONS:
 	case ST_OMP_ORDERED:
 	case ST_OMP_CRITICAL:
+	case ST_OMP_MASKED:
 	case ST_OMP_MASTER:
 	case ST_OMP_SINGLE:
 	case ST_OMP_TARGET:
@@ -5711,8 +5794,12 @@ parse_executable (gfc_statement st)
 	case ST_OMP_PARALLEL_DO:
 	case ST_OMP_PARALLEL_DO_SIMD:
 	case ST_OMP_PARALLEL_LOOP:
+	case ST_OMP_PARALLEL_MASKED_TASKLOOP:
+	case ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	case ST_OMP_PARALLEL_MASTER_TASKLOOP:
 	case ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+	case ST_OMP_MASKED_TASKLOOP:
+	case ST_OMP_MASKED_TASKLOOP_SIMD:
 	case ST_OMP_MASTER_TASKLOOP:
 	case ST_OMP_MASTER_TASKLOOP_SIMD:
 	case ST_OMP_SIMD:
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 592364689f9..b0087be5068 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -10810,6 +10810,9 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
 	case EXEC_OMP_DO:
 	case EXEC_OMP_DO_SIMD:
 	case EXEC_OMP_LOOP:
+	case EXEC_OMP_MASKED:
+	case EXEC_OMP_MASKED_TASKLOOP:
+	case EXEC_OMP_MASKED_TASKLOOP_SIMD:
 	case EXEC_OMP_MASTER:
 	case EXEC_OMP_MASTER_TASKLOOP:
 	case EXEC_OMP_MASTER_TASKLOOP_SIMD:
@@ -10818,6 +10821,9 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
 	case EXEC_OMP_PARALLEL_DO:
 	case EXEC_OMP_PARALLEL_DO_SIMD:
 	case EXEC_OMP_PARALLEL_LOOP:
+	case EXEC_OMP_PARALLEL_MASKED:
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	case EXEC_OMP_PARALLEL_MASTER:
 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
@@ -11785,6 +11791,9 @@ gfc_resolve_code (gfc_code *code, gfc_namespace *ns)
 	    case EXEC_OMP_PARALLEL:
 	    case EXEC_OMP_PARALLEL_DO:
 	    case EXEC_OMP_PARALLEL_DO_SIMD:
+	    case EXEC_OMP_PARALLEL_MASKED:
+	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	    case EXEC_OMP_PARALLEL_MASTER:
 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
@@ -12240,6 +12249,9 @@ start:
 	case EXEC_OMP_MASTER:
 	case EXEC_OMP_MASTER_TASKLOOP:
 	case EXEC_OMP_MASTER_TASKLOOP_SIMD:
+	case EXEC_OMP_MASKED:
+	case EXEC_OMP_MASKED_TASKLOOP:
+	case EXEC_OMP_MASKED_TASKLOOP_SIMD:
 	case EXEC_OMP_ORDERED:
 	case EXEC_OMP_SCAN:
 	case EXEC_OMP_SECTIONS:
@@ -12281,6 +12293,9 @@ start:
 	case EXEC_OMP_PARALLEL_DO:
 	case EXEC_OMP_PARALLEL_DO_SIMD:
 	case EXEC_OMP_PARALLEL_LOOP:
+	case EXEC_OMP_PARALLEL_MASKED:
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	case EXEC_OMP_PARALLEL_MASTER:
 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index 6ae1df612a7..f61f88adcc5 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -227,13 +227,19 @@ gfc_free_statement (gfc_code *p)
     case EXEC_OMP_DO_SIMD:
     case EXEC_OMP_LOOP:
     case EXEC_OMP_END_SINGLE:
+    case EXEC_OMP_MASKED_TASKLOOP:
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_ORDERED:
+    case EXEC_OMP_MASKED:
     case EXEC_OMP_PARALLEL:
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_LOOP:
+    case EXEC_OMP_PARALLEL_MASKED:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 3d3b35e9509..623c21fc790 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -4047,6 +4047,21 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
+  if (clauses->filter)
+    {
+      tree filter;
+
+      gfc_init_se (&se, NULL);
+      gfc_conv_expr (&se, clauses->filter);
+      gfc_add_block_to_block (block, &se.pre);
+      filter = gfc_evaluate_now (se.expr, block);
+      gfc_add_block_to_block (block, &se.post);
+
+      c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER);
+      OMP_CLAUSE_FILTER_EXPR (c) = filter;
+      omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+    }
+
   if (clauses->hint)
     {
       tree hint;
@@ -5389,6 +5404,26 @@ gfc_trans_omp_master (gfc_code *code)
   return build1_v (OMP_MASTER, stmt);
 }
 
+static tree
+gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
+{
+  stmtblock_t block;
+  tree body = gfc_trans_code (code->block->next);
+  if (IS_EMPTY_STMT (body))
+    return body;
+  if (!clauses)
+    clauses = code->ext.omp_clauses;
+  gfc_start_block (&block);
+  tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
+  tree stmt = make_node (OMP_MASKED);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_MASKED_BODY (stmt) = body;
+  OMP_MASKED_CLAUSES (stmt) = omp_clauses;
+  gfc_add_expr_to_block (&block, stmt);
+  return gfc_finish_block (&block);
+}
+
+
 static tree
 gfc_trans_omp_ordered (gfc_code *code)
 {
@@ -5432,6 +5467,7 @@ enum
   GFC_OMP_SPLIT_TEAMS,
   GFC_OMP_SPLIT_TARGET,
   GFC_OMP_SPLIT_TASKLOOP,
+  GFC_OMP_SPLIT_MASKED,
   GFC_OMP_SPLIT_NUM
 };
 
@@ -5443,7 +5479,8 @@ enum
   GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
   GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
   GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
-  GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP)
+  GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP),
+  GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED)
 };
 
 /* If a var is in lastprivate/firstprivate/reduction but not in a
@@ -5632,10 +5669,24 @@ gfc_split_omp_clauses (gfc_code *code,
       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
       innermost = GFC_OMP_SPLIT_SIMD;
       break;
+    case EXEC_OMP_PARALLEL_MASKED:
+      mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED;
+      innermost = GFC_OMP_SPLIT_MASKED;
+      break;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+      mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
+	      | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
+      innermost = GFC_OMP_SPLIT_TASKLOOP;
+      break;
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
       innermost = GFC_OMP_SPLIT_TASKLOOP;
       break;
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+      mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
+	      | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
+      innermost = GFC_OMP_SPLIT_SIMD;
+      break;
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
       innermost = GFC_OMP_SPLIT_SIMD;
@@ -5692,10 +5743,18 @@ gfc_split_omp_clauses (gfc_code *code,
       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
       innermost = GFC_OMP_SPLIT_DO;
       break;
+    case EXEC_OMP_MASKED_TASKLOOP:
+      mask = GFC_OMP_SPLIT_MASKED | GFC_OMP_SPLIT_TASKLOOP;
+      innermost = GFC_OMP_SPLIT_TASKLOOP;
+      break;
     case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_TASKLOOP:
       innermost = GFC_OMP_SPLIT_TASKLOOP;
       break;
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
+      mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
+      innermost = GFC_OMP_SPLIT_SIMD;
+      break;
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_TASKLOOP_SIMD:
       mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
@@ -5814,6 +5873,8 @@ gfc_split_omp_clauses (gfc_code *code,
 	  clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
 	    = code->ext.omp_clauses->if_expr;
 	}
+      if (mask & GFC_OMP_MASK_MASKED)
+	clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter;
       if ((mask & GFC_OMP_MASK_DO) && !is_loop)
 	{
 	  /* First the clauses that are unique to some constructs.  */
@@ -5896,16 +5957,18 @@ gfc_split_omp_clauses (gfc_code *code,
 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
 	    = code->ext.omp_clauses->collapse;
 	}
-      /* Private clause is supported on all constructs,
-	 it is enough to put it on the innermost one.  For
+      /* Private clause is supported on all constructs but master/masked,
+	 it is enough to put it on the innermost one except for master/masked.  For
 	 !$ omp parallel do put it on parallel though,
 	 as that's what we did for OpenMP 3.1.  */
-      clausesa[innermost == GFC_OMP_SPLIT_DO && !is_loop
+      clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop)
+		|| code->op == EXEC_OMP_PARALLEL_MASTER
+		|| code->op == EXEC_OMP_PARALLEL_MASKED)
 	       ? (int) GFC_OMP_SPLIT_PARALLEL
 	       : innermost].lists[OMP_LIST_PRIVATE]
 	= code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
       /* Firstprivate clause is supported on all constructs but
-	 simd.  Put it on the outermost of those and duplicate
+	 simd and masked/master.  Put it on the outermost of those and duplicate
 	 on parallel and teams.  */
       if (mask & GFC_OMP_MASK_TARGET)
 	clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
@@ -6588,43 +6651,66 @@ gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
 }
 
 static tree
-gfc_trans_omp_master_taskloop (gfc_code *code, gfc_exec_op op)
+gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op)
 {
+  gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
   stmtblock_t block;
   tree stmt;
 
-  gfc_start_block (&block);
+  if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
+      && code->op != EXEC_OMP_MASTER_TASKLOOP)
+    gfc_split_omp_clauses (code, clausesa);
+
   pushlevel ();
-  if (op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
+  if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD
+      || op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
     stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD);
   else
     {
-      gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
-      gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP);
-      if (op != code->op)
-	gfc_split_omp_clauses (code, clausesa);
+      gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP
+		  || op == EXEC_OMP_MASTER_TASKLOOP);
       stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
-			       op != code->op
+			       code->op != EXEC_OMP_MASTER_TASKLOOP
 			       ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
 			       : code->ext.omp_clauses, NULL);
-      if (op != code->op)
-	gfc_free_split_omp_clauses (code, clausesa);
     }
   if (TREE_CODE (stmt) != BIND_EXPR)
     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
   else
     poplevel (0, 0);
-  stmt = build1_v (OMP_MASTER, stmt);
-  gfc_add_expr_to_block (&block, stmt);
+  gfc_start_block (&block);
+  if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD)
+    {
+      tree clauses = gfc_trans_omp_clauses (&block,
+					    &clausesa[GFC_OMP_SPLIT_MASKED],
+					    code->loc);
+      tree msk = make_node (OMP_MASKED);
+      TREE_TYPE (msk) = void_type_node;
+      OMP_MASKED_BODY (msk) = stmt;
+      OMP_MASKED_CLAUSES (msk) = clauses;
+      OMP_MASKED_COMBINED (msk) = 1;
+      gfc_add_expr_to_block (&block, msk);
+    }
+  else
+    {
+      gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP
+		  || op == EXEC_OMP_MASTER_TASKLOOP_SIMD);
+      stmt = build1_v (OMP_MASTER, stmt);
+      gfc_add_expr_to_block (&block, stmt);
+    }
+  if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
+      && code->op != EXEC_OMP_MASTER_TASKLOOP)
+    gfc_free_split_omp_clauses (code, clausesa);
   return gfc_finish_block (&block);
 }
 
 static tree
-gfc_trans_omp_parallel_master (gfc_code *code)
+gfc_trans_omp_parallel_master_masked (gfc_code *code)
 {
   stmtblock_t block;
   tree stmt, omp_clauses;
   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
+  bool parallel_combined = false;
 
   if (code->op != EXEC_OMP_PARALLEL_MASTER)
     gfc_split_omp_clauses (code, clausesa);
@@ -6635,19 +6721,33 @@ gfc_trans_omp_parallel_master (gfc_code *code)
 				       ? code->ext.omp_clauses
 				       : &clausesa[GFC_OMP_SPLIT_PARALLEL],
 				       code->loc);
-  if (code->op != EXEC_OMP_PARALLEL_MASTER)
-    gfc_free_split_omp_clauses (code, clausesa);
   pushlevel ();
   if (code->op == EXEC_OMP_PARALLEL_MASTER)
     stmt = gfc_trans_omp_master (code);
+  else if (code->op == EXEC_OMP_PARALLEL_MASKED)
+    stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]);
   else
     {
-      gcc_assert (code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
-		  || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD);
-      gfc_exec_op op = (code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
-			? EXEC_OMP_MASTER_TASKLOOP
-			: EXEC_OMP_MASTER_TASKLOOP_SIMD);
-      stmt = gfc_trans_omp_master_taskloop (code, op);
+      gfc_exec_op op;
+      switch (code->op)
+	{
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+	  op = EXEC_OMP_MASKED_TASKLOOP;
+	  break;
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+	  op = EXEC_OMP_MASKED_TASKLOOP_SIMD;
+	  break;
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+	  op = EXEC_OMP_MASTER_TASKLOOP;
+	  break;
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+	  op = EXEC_OMP_MASTER_TASKLOOP_SIMD;
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      stmt = gfc_trans_omp_master_masked_taskloop (code, op);
+      parallel_combined = true;
     }
   if (TREE_CODE (stmt) != BIND_EXPR)
     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
@@ -6655,8 +6755,19 @@ gfc_trans_omp_parallel_master (gfc_code *code)
     poplevel (0, 0);
   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
 		     void_type_node, stmt, omp_clauses);
-  OMP_PARALLEL_COMBINED (stmt) = 1;
+  /* masked does have just filter clause, but during gimplification
+     isn't represented by a gimplification omp context, so for
+       !$omp parallel masked don't set OMP_PARALLEL_COMBINED,
+     so that
+       !$omp parallel masked
+       !$omp taskloop simd lastprivate (x)
+     isn't confused with
+       !$omp parallel masked taskloop simd lastprivate (x)  */
+  if (parallel_combined)
+    OMP_PARALLEL_COMBINED (stmt) = 1;
   gfc_add_expr_to_block (&block, stmt);
+  if (code->op != EXEC_OMP_PARALLEL_MASTER)
+    gfc_free_split_omp_clauses (code, clausesa);
   return gfc_finish_block (&block);
 }
 
@@ -6969,11 +7080,15 @@ gfc_trans_omp_directive (gfc_code *code)
       return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
     case EXEC_OMP_FLUSH:
       return gfc_trans_omp_flush (code);
+    case EXEC_OMP_MASKED:
+      return gfc_trans_omp_masked (code, NULL);
     case EXEC_OMP_MASTER:
       return gfc_trans_omp_master (code);
+    case EXEC_OMP_MASKED_TASKLOOP:
+    case EXEC_OMP_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
-      return gfc_trans_omp_master_taskloop (code, code->op);
+      return gfc_trans_omp_master_masked_taskloop (code, code->op);
     case EXEC_OMP_ORDERED:
       return gfc_trans_omp_ordered (code);
     case EXEC_OMP_PARALLEL:
@@ -6984,10 +7099,13 @@ gfc_trans_omp_directive (gfc_code *code)
       return gfc_trans_omp_parallel_do (code, true, NULL, NULL);
     case EXEC_OMP_PARALLEL_DO_SIMD:
       return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
+    case EXEC_OMP_PARALLEL_MASKED:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
-      return gfc_trans_omp_parallel_master (code);
+      return gfc_trans_omp_parallel_master_masked (code);
     case EXEC_OMP_PARALLEL_SECTIONS:
       return gfc_trans_omp_parallel_sections (code);
     case EXEC_OMP_PARALLEL_WORKSHARE:
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 275d6a28f1c..ce5b2f8d594 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -2156,6 +2156,9 @@ trans_code (gfc_code * code, tree cond)
 	case EXEC_OMP_DO_SIMD:
 	case EXEC_OMP_LOOP:
 	case EXEC_OMP_FLUSH:
+	case EXEC_OMP_MASKED:
+	case EXEC_OMP_MASKED_TASKLOOP:
+	case EXEC_OMP_MASKED_TASKLOOP_SIMD:
 	case EXEC_OMP_MASTER:
 	case EXEC_OMP_MASTER_TASKLOOP:
 	case EXEC_OMP_MASTER_TASKLOOP_SIMD:
@@ -2164,6 +2167,9 @@ trans_code (gfc_code * code, tree cond)
 	case EXEC_OMP_PARALLEL_DO:
 	case EXEC_OMP_PARALLEL_DO_SIMD:
 	case EXEC_OMP_PARALLEL_LOOP:
+	case EXEC_OMP_PARALLEL_MASKED:
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
 	case EXEC_OMP_PARALLEL_MASTER:
 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-1.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-1.f90
new file mode 100644
index 00000000000..1bd61760ced
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-1.f90
@@ -0,0 +1,94 @@
+! { dg-additional-options "-ffree-line-length-none" }
+subroutine foo (x, a)
+  implicit none
+  integer, value :: x
+  integer, contiguous :: a(0:)
+  external :: bar
+  integer :: i
+
+  !$omp masked
+   call bar ()
+  !$omp end masked
+
+  !$omp masked filter (0)
+   call bar ()
+  !$omp end masked
+
+  !$omp masked filter (7)
+   call bar ()
+  !$omp end masked
+
+  !$omp masked filter (x)
+   call bar ()
+  !$omp end masked
+
+  !$omp masked taskloop simd filter (x) grainsize (12) simdlen (4)
+    do i = 0, 127
+      a(i) = i
+    end do
+  !$omp end masked taskloop simd
+
+  !$omp parallel masked filter (x) firstprivate (x)
+    call bar ()
+  !$omp end parallel masked
+
+  !$omp masked
+    !$omp masked filter (0)
+      !$omp masked filter (x)
+      !$omp end masked
+    !$omp end masked
+  !$omp end masked
+end
+
+subroutine foobar (d, f, fi, p, s, g, i1, i2, l, ll, nth, ntm, pp, q, r, r2)
+  implicit none (type, external)
+  logical :: i1, i2, fi
+  integer :: i, d, f, p, s, g, l, ll, nth, ntm, pp, q, r, r2
+  allocatable :: q
+  integer, save :: t
+  !$omp threadprivate (t)
+
+  !$omp parallel masked &
+  !$omp&  private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) &
+  !$omp&  num_threads (nth) proc_bind(spread) copyin(t) filter (d)  ! allocate (f)
+    !
+  !$omp end parallel masked
+
+  !$omp taskgroup task_reduction (+:r2)  ! allocate (r2)
+    !$omp masked taskloop &
+    !$omp&  private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) &
+    !$omp&  reduction(default, +:r) in_reduction(+:r2) filter (d)  ! allocate (f)
+    do i = 0, 63
+      ll = ll + 1
+    end do
+    !$omp end masked taskloop
+  !$omp end taskgroup
+
+  !$omp taskgroup task_reduction (+:r2)  ! allocate (r2)
+    !$omp masked taskloop simd &
+    !$omp&  private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) &
+    !$omp&  safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) &
+    !$omp&  order(concurrent) filter (d)  !  allocate (f)
+    do i = 0, 63
+      ll = ll + 1
+    end do
+    !$omp end masked taskloop simd
+  !$omp end taskgroup
+
+  !$omp parallel masked taskloop &
+    !$omp&  private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) &
+    !$omp&  reduction(default, +:r) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) filter (d)  ! allocate (f)
+    do i = 0, 63
+      ll = ll + 1
+    end do
+  !$omp end parallel masked taskloop
+
+  !$omp parallel masked taskloop simd &
+    !$omp&  private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) &
+    !$omp&  safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) &
+    !$omp&  order(concurrent) filter (d)  ! allocate (f)
+    do i = 0, 63
+      ll = ll + 1
+    end do
+  !$omp end parallel masked taskloop simd
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-2.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-2.f90
new file mode 100644
index 00000000000..95ef78c0664
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-2.f90
@@ -0,0 +1,46 @@
+module m
+  implicit none (external, type)
+  type t
+  end type t
+contains
+subroutine foo (x, y, z, a)
+  external :: bar
+  type(t) :: x
+  integer :: y
+  real :: z
+  integer :: a(4)
+
+  !$omp masked filter (x)  ! { dg-error "FILTER clause at .1. requires a scalar INTEGER expression" }
+    call bar ()
+  !$omp end masked
+
+  !$omp masked filter (y)  ! OK
+    call bar ()
+  !$omp end masked
+
+  !$omp masked filter (z)  ! { dg-error "FILTER clause at .1. requires a scalar INTEGER expression" }
+    call bar ()
+  !$omp end masked
+
+  !$omp masked filter (a)  ! { dg-error "FILTER clause at .1. requires a scalar INTEGER expression" }
+    call bar ()
+  !$omp end masked
+
+  !$omp masked filter (0.0)  ! { dg-error "FILTER clause at .1. requires a scalar INTEGER expression" }
+    call bar ()
+  !$omp end masked
+
+  !$omp masked filter ([1])  ! { dg-error "FILTER clause at .1. requires a scalar INTEGER expression" }
+    call bar ()
+  !$omp end masked
+
+  !$omp masked filter (-1)  ! { dg-warning "INTEGER expression of FILTER clause at .1. must be non-negative" }
+    call bar ()
+  !$omp end masked
+end
+end module
+
+subroutine bar
+  !$omp masked filter (0) filter (0)  ! { dg-error "27: Failed to match clause" }
+    call foobar
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-3.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-3.f90
new file mode 100644
index 00000000000..49c633d21a5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-3.f90
@@ -0,0 +1,12 @@
+subroutine foo
+
+  !$omp masked
+     goto 55  ! { dg-error "invalid branch to/from OpenMP structured block" }
+              ! { dg-warning "Legacy Extension: Label at .1. is not in the same block as the GOTO statement" "" { target *-*-* } .-1 }
+  !$omp end masked
+
+  !$omp masked
+55  continue  ! { dg-warning "Legacy Extension: Label at .1. is not in the same block as the GOTO statement" }
+    return    ! { dg-error "invalid branch to/from OpenMP structured block" }
+  !$omp end masked
+end subroutine foo
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-combined-1.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-combined-1.f90
new file mode 100644
index 00000000000..23ffb084ee1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-combined-1.f90
@@ -0,0 +1,65 @@
+subroutine foo (a, f)
+  implicit none (type, external)
+  interface
+    subroutine bar (x)
+      integer :: x
+    end subroutine
+  end interface
+
+  integer, value :: f
+  integer, contiguous :: a(0:)
+  integer :: i, j, k, u, v, w, x, y, z
+
+  !$omp parallel masked default(none) private (k) filter (f) firstprivate (f)
+    call bar (k)
+  !$omp end parallel masked
+
+  !$omp parallel masked default(none) private (k)
+    call bar (k)
+  !$omp end parallel masked
+  
+  !$omp parallel default(none) firstprivate(a, f) shared(x, y, z)
+    !$omp masked taskloop reduction (+:x) default(none) firstprivate(a) filter (f)
+      do i = 0, 63
+        x = x + a(i)
+      end do
+    !$omp end masked taskloop
+    !$omp masked taskloop simd reduction (+:y) default(none) firstprivate(a) private (i) filter (f)
+      do i = 0, 63
+        y = y + a(i)
+      end do
+    !$omp end masked taskloop simd
+    !$omp masked taskloop simd reduction (+:y) default(none) firstprivate(a) private (i)
+      do i = 0, 63
+        y = y + a(i)
+      end do
+    !$omp end masked taskloop simd
+    !$omp masked taskloop simd collapse(2) reduction (+:z) default(none) firstprivate(a) private (i, j) filter (f)
+      do j = 0, 0
+        do i = 0, 63
+          z = z + a(i)
+        end do
+      end do
+    !$omp end masked taskloop simd
+  !$omp end parallel
+
+  !$omp parallel masked taskloop reduction (+:u) default(none) firstprivate(a, f) filter (f)
+    do i = 0, 63
+      u = u + a(i)
+    end do
+  !$omp end parallel masked taskloop
+
+  !$omp parallel masked taskloop simd reduction (+:v) default(none) firstprivate(a, f) filter (f)
+    do i = 0, 63
+      v = v + a(i)
+    end do
+  !$omp end parallel masked taskloop simd
+
+  !$omp parallel masked taskloop simd collapse(2) reduction (+:w) default(none) firstprivate(a, f) filter (f)
+    do j = 0, 0
+      do i = 0, 63
+        w = w + a(i)
+      end do
+    end do
+  !$omp end parallel masked taskloop simd
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-combined-2.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-combined-2.f90
new file mode 100644
index 00000000000..c94425fd0bd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-combined-2.f90
@@ -0,0 +1,24 @@
+subroutine foo (a)
+  implicit none (external, type)
+  integer, contiguous :: a(0:)
+  integer :: i, r, s
+  r = 0; s = 0
+
+  ! In 'parallel masked taskloop', in_reduction is not permitted.
+
+  !$omp taskgroup task_reduction(+:r)
+    !$omp parallel masked taskloop in_reduction(+:r)  ! { dg-error "36: Failed to match clause" }
+      do i = 0, 63
+        r = r + a(i)
+      end do
+    !!$omp end parallel masked taskloop
+  !$omp end taskgroup
+
+  !$omp taskgroup task_reduction(+:s)
+    !$omp parallel masked taskloop simd in_reduction(+:s)  ! { dg-error "41: Failed to match clause" }
+      do i = 0, 63
+        s = s + a(i)
+      end do
+    !!$omp end parallel masked taskloop simd
+  !$omp end taskgroup
+end
diff --git a/libgomp/testsuite/libgomp.fortran/masked-1.f90 b/libgomp/testsuite/libgomp.fortran/masked-1.f90
new file mode 100644
index 00000000000..3ecd1aa48dc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/masked-1.f90
@@ -0,0 +1,141 @@
+module m
+  use omp_lib
+  implicit none (type, external)
+contains
+  subroutine foo (x, a)
+    integer, value :: x
+    integer, contiguous :: a(0:)
+    integer :: i
+
+    !$omp masked
+      if (omp_get_thread_num () /= 0) &
+        stop 1
+      a(128) = a(128) + 1
+    !$omp end masked
+
+    !$omp masked filter (0)
+      if (omp_get_thread_num () /= 0) &
+        stop 2
+      a(129) = a(129) + 1
+    !$omp end masked
+
+    !$omp masked filter (7)
+      if (omp_get_thread_num () /= 7) &
+        stop 3
+      a(130) = a(130) + 1
+    !$omp end masked
+
+    !$omp masked filter (x)
+      if (omp_get_thread_num () /= x) &
+        stop 4
+      a(131) = a(131) + 1
+    !$omp end masked
+
+    !$omp masked taskloop !simd filter (x) grainsize (12) simdlen (4)
+      do i = 0, 127
+        a(i) = a(i) + i
+      end do
+    !$omp end masked taskloop !simd
+  end
+end
+
+program main
+  use m
+  implicit none (type, external)
+  integer :: i
+  integer :: a(0:135)
+
+  a = 0
+
+  !$omp parallel num_threads (4)
+    call foo (4, a)
+  !$omp end parallel
+  do i = 0, 127
+    if (a(i) /= 0) &
+      stop 5
+  end do
+  if (a(128) /= 1 .or. a(129) /= 1 .or. a(130) /= 0 .or. a(131) /= 0) &
+    stop 6
+
+  !$omp parallel num_threads (4)
+    call foo (3, a)
+  !$omp end parallel
+  do i = 0, 127
+    ! FIXME vvvvvvvvvvvv
+    if (a(i) /= i) then
+      print *, "WRONG RESULT (7) -> PR 101899"
+      ! fix result:
+      block
+        integer :: j
+        a(0:127) = [(j, j = 0, 127)]
+      end block
+      exit
+    end if
+    ! FIXME ^^^^^^
+    if (a(i) /= i) &
+      stop 7
+  end do
+  if (a(128) /= 2 .or. a(129) /= 2 .or. a(130) /= 0 .or. a(131) /= 1) &
+    stop 8
+
+  !$omp parallel num_threads (8)
+    call foo (8, a)
+  !$omp end parallel
+  do i = 0, 127
+    if (a(i) /= i) &
+      stop 9
+  end do
+  if (a(128) /= 3 .or. a(129) /= 3 .or. a(130) /= 1 .or. a(131) /= 1) &
+    stop 10
+
+  !$omp parallel num_threads (8)
+    call foo (6, a)
+  !$omp end parallel
+  do i = 0, 127
+    ! FIXME vvvvvvvvvvvv
+    if (a(i) /= 2*i) then
+      print *, "WRONG RESULT (11) -> PR 101899"
+      ! fix result:
+      block
+        integer :: j
+        a(0:127) = [(2*j, j = 0, 127)]
+      end block
+      exit
+    end if
+    ! FIXME ^^^^^^
+    if (a(i) /= 2 * i) &
+      stop 11
+  end do
+  if (a(128) /= 4 .or. a(129) /= 4 .or. a(130) /= 2 .or. a(131) /= 2) &
+    stop 12
+
+  do i = 0, 7
+    a(i) = 0
+  end do
+  ! The filter expression can evaluate to different values in different threads.
+  !$omp parallel masked num_threads (8) filter (omp_get_thread_num () + 1)
+    a(omp_get_thread_num ()) = a(omp_get_thread_num ()) + 1
+  !$omp end parallel masked
+  do i = 0, 7
+    if (a(i) /= 0) &
+      stop 13
+  end do
+
+  ! And multiple threads can be filtered.
+  !$omp parallel masked num_threads (8) filter (iand (omp_get_thread_num (), not(1)))
+    a(omp_get_thread_num ()) = a(omp_get_thread_num ()) + 1
+  !$omp end parallel masked
+  do i = 0, 7
+    block
+      integer :: j
+      j = iand (i, 1)
+      if (j /= 0) then
+        j = 0
+      else
+        j = 1
+      end if
+      if (a(i) /= j) &
+        stop 14
+    end block
+  end do
+end program main

Reply via email to