diff mbox series

Fortran/OpenMP: Support (parallel) master taskloop (simd) [PR99928]

Message ID f7668e6b-ec6f-58b2-4d1e-b8cf583f3132@codesourcery.com
State New
Headers show
Series Fortran/OpenMP: Support (parallel) master taskloop (simd) [PR99928] | expand

Commit Message

Tobias Burnus June 1, 2021, 9:53 a.m. UTC
(PR 99928 is mainly about handling clauses in combined constructs.
but it sees some related commits like this one. The PR is not
fully fixed for C/C++ and for Fortran a bit more is missing.)

This patch adds '(parallel) master taskloop (simd)' support to gfortran.

For full parsing support for the Fortran version of the C/C++ testcases pr99928-*.c,
parsing support for 'loop' (+ combined constructs) and reduction with an array (slice)
is missing. – And, of course, doing FE fixes for handling the clauses,
similar to what has been/is being done for C/C++.
(No attempt has been made in this patch to fix long-standing
combined-clause handling issues.)

As bug fix, 'taskloop simd reduction(...)' is now supported and
'taskloop simd reduction(task,...' is now diagnosed by the FE.

Tobias

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf

Comments

Jakub Jelinek June 1, 2021, 10:02 a.m. UTC | #1
On Tue, Jun 01, 2021 at 11:53:12AM +0200, Tobias Burnus wrote:
> Fortran/OpenMP: Support (parallel) master taskloop (simd) [PR99928]
> 
> 	PR middle-end/99928
> 
> gcc/fortran/ChangeLog:
> 
> 	* dump-parse-tree.c (show_omp_node, show_code_node): Handle
> 	(parallel) master taskloop (simd).
> 	* frontend-passes.c (gfc_code_walker): Set in_omp_workshare
> 	to false for parallel master taskloop (simd).
> 	* gfortran.h (enum gfc_statement):
> 	Add ST_OMP_(END_)(PARALLEL_)MASTER_TASKLOOP(_SIMD).
> 	(enum gfc_exec_op): EXEC_OMP_(PARALLEL_)MASTER_TASKLOOP(_SIMD).
> 	* match.h (gfc_match_omp_master_taskloop,
> 	gfc_match_omp_master_taskloop_simd,
> 	gfc_match_omp_parallel_master_taskloop,
> 	gfc_match_omp_parallel_master_taskloop_simd): New prototype.
> 	* openmp.c (gfc_match_omp_parallel_master_taskloop,
> 	gfc_match_omp_parallel_master_taskloop_simd,
> 	gfc_match_omp_master_taskloop,
> 	gfc_match_omp_master_taskloop_simd): New.
> 	(gfc_match_omp_taskloop_simd): Permit 'reduction' clause.
> 	(resolve_omp_clauses): Handle new combined directives; remove
> 	inscan-reduction check to reduce multiple errors; add
> 	task-reduction error for 'taskloop simd'.
>         (gfc_resolve_omp_parallel_blocks,
> 	resolve_omp_do, omp_code_to_statement,
> 	gfc_resolve_omp_directive): Handle new combined constructs.
> 	* parse.c (decode_omp_directive, next_statement,
> 	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.c (trans_code): Likewise.
> 	* trans-openmp.c (gfc_split_omp_clauses,
> 	gfc_trans_omp_directive): Likewise.
> 	(gfc_trans_omp_parallel_master): Move after gfc_trans_omp_master_taskloop;
> 	handle parallel master taskloop (simd) as well.
> 	(gfc_trans_omp_taskloop): Take gfc_exec_op as arg.
> 	(gfc_trans_omp_master_taskloop): New.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gfortran.dg/gomp/reduction5.f90: Remove dg-error the issue is
> 	now diagnosed with error output less. 

The above sentence is weird.  I'd expect semicolon or comma before the
and less error output instead of error output less.

> 	* gfortran.dg/gomp/scan-1.f90: Likewise.
> 	* gfortran.dg/gomp/pr99928-3.f90: New test.
> 	* gfortran.dg/gomp/taskloop-1.f90: New test.

Otherwise LGTM.

	Jakub
Tobias Burnus June 1, 2021, 1:18 p.m. UTC | #2
On 01.06.21 12:02, Jakub Jelinek wrote:
>>      * gfortran.dg/gomp/scan-1.f90: Likewise.
>>      * gfortran.dg/gomp/pr99928-3.f90: New test.
>>      * gfortran.dg/gomp/taskloop-1.f90: New test.

> Otherwise LGTM.
>       Jakub

Thanks for the review! – I just saw that I missed to include another
testcase – unless there I comments, I will commit it later.

Tobias

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf
diff mbox series

Patch

Fortran/OpenMP: Support (parallel) master taskloop (simd) [PR99928]

	PR middle-end/99928

gcc/fortran/ChangeLog:

	* dump-parse-tree.c (show_omp_node, show_code_node): Handle
	(parallel) master taskloop (simd).
	* frontend-passes.c (gfc_code_walker): Set in_omp_workshare
	to false for parallel master taskloop (simd).
	* gfortran.h (enum gfc_statement):
	Add ST_OMP_(END_)(PARALLEL_)MASTER_TASKLOOP(_SIMD).
	(enum gfc_exec_op): EXEC_OMP_(PARALLEL_)MASTER_TASKLOOP(_SIMD).
	* match.h (gfc_match_omp_master_taskloop,
	gfc_match_omp_master_taskloop_simd,
	gfc_match_omp_parallel_master_taskloop,
	gfc_match_omp_parallel_master_taskloop_simd): New prototype.
	* openmp.c (gfc_match_omp_parallel_master_taskloop,
	gfc_match_omp_parallel_master_taskloop_simd,
	gfc_match_omp_master_taskloop,
	gfc_match_omp_master_taskloop_simd): New.
	(gfc_match_omp_taskloop_simd): Permit 'reduction' clause.
	(resolve_omp_clauses): Handle new combined directives; remove
	inscan-reduction check to reduce multiple errors; add
	task-reduction error for 'taskloop simd'.
        (gfc_resolve_omp_parallel_blocks,
	resolve_omp_do, omp_code_to_statement,
	gfc_resolve_omp_directive): Handle new combined constructs.
	* parse.c (decode_omp_directive, next_statement,
	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.c (trans_code): Likewise.
	* trans-openmp.c (gfc_split_omp_clauses,
	gfc_trans_omp_directive): Likewise.
	(gfc_trans_omp_parallel_master): Move after gfc_trans_omp_master_taskloop;
	handle parallel master taskloop (simd) as well.
	(gfc_trans_omp_taskloop): Take gfc_exec_op as arg.
	(gfc_trans_omp_master_taskloop): New.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/reduction5.f90: Remove dg-error the issue is
	now diagnosed with error output less. 
	* gfortran.dg/gomp/scan-1.f90: Likewise.
	* gfortran.dg/gomp/pr99928-3.f90: New test.
	* gfortran.dg/gomp/taskloop-1.f90: New test.

 gcc/fortran/dump-parse-tree.c                 |  12 +++
 gcc/fortran/frontend-passes.c                 |   2 +
 gcc/fortran/gfortran.h                        |  10 +-
 gcc/fortran/match.h                           |   4 +
 gcc/fortran/openmp.c                          |  85 ++++++++++++++--
 gcc/fortran/parse.c                           |  73 +++++++++++++-
 gcc/fortran/resolve.c                         |  10 ++
 gcc/fortran/st.c                              |   4 +
 gcc/fortran/trans-openmp.c                    | 112 ++++++++++++++++-----
 gcc/fortran/trans.c                           |   4 +
 gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90  | 139 ++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/gomp/reduction5.f90 |   4 +-
 gcc/testsuite/gfortran.dg/gomp/scan-1.f90     |   4 +-
 gcc/testsuite/gfortran.dg/gomp/taskloop-1.f90 | 126 +++++++++++++++++++++++
 14 files changed, 550 insertions(+), 39 deletions(-)

 gcc/fortran/dump-parse-tree.c                 |  12 +++
 gcc/fortran/frontend-passes.c                 |   2 +
 gcc/fortran/gfortran.h                        |  10 +-
 gcc/fortran/match.h                           |   4 +
 gcc/fortran/openmp.c                          |  85 ++++++++++++++--
 gcc/fortran/parse.c                           |  73 +++++++++++++-
 gcc/fortran/resolve.c                         |  10 ++
 gcc/fortran/st.c                              |   4 +
 gcc/fortran/trans-openmp.c                    | 112 ++++++++++++++++-----
 gcc/fortran/trans.c                           |   4 +
 gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90  | 139 ++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/gomp/reduction5.f90 |   4 +-
 gcc/testsuite/gfortran.dg/gomp/scan-1.f90     |   4 +-
 gcc/testsuite/gfortran.dg/gomp/taskloop-1.f90 | 126 +++++++++++++++++++++++
 14 files changed, 550 insertions(+), 39 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 93ff572cbd2..0e7fe1cc3f3 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1898,12 +1898,18 @@  show_omp_node (int level, gfc_code *c)
     case EXEC_OMP_DO_SIMD: name = "DO SIMD"; break;
     case EXEC_OMP_FLUSH: name = "FLUSH"; 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;
     case EXEC_OMP_ORDERED: name = "ORDERED"; break;
     case EXEC_OMP_DEPOBJ: name = "DEPOBJ"; break;
     case EXEC_OMP_PARALLEL: name = "PARALLEL"; break;
     case EXEC_OMP_PARALLEL_DO: name = "PARALLEL DO"; break;
     case EXEC_OMP_PARALLEL_DO_SIMD: name = "PARALLEL DO SIMD"; break;
     case EXEC_OMP_PARALLEL_MASTER: name = "PARALLEL MASTER"; break;
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+      name = "PARALLEL MASTER TASKLOOP"; break;
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+      name = "PARALLEL MASTER TASKLOOP SIMD"; break;
     case EXEC_OMP_PARALLEL_SECTIONS: name = "PARALLEL SECTIONS"; break;
     case EXEC_OMP_PARALLEL_WORKSHARE: name = "PARALLEL WORKSHARE"; break;
     case EXEC_OMP_SCAN: name = "SCAN"; break;
@@ -1976,6 +1982,8 @@  show_omp_node (int level, gfc_code *c)
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_SECTIONS:
     case EXEC_OMP_PARALLEL_WORKSHARE:
     case EXEC_OMP_SCAN:
@@ -3184,11 +3192,15 @@  show_code_node (int level, gfc_code *c)
     case EXEC_OMP_DO_SIMD:
     case EXEC_OMP_FLUSH:
     case EXEC_OMP_MASTER:
+    case EXEC_OMP_MASTER_TASKLOOP:
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_ORDERED:
     case EXEC_OMP_PARALLEL:
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_SECTIONS:
     case EXEC_OMP_PARALLEL_WORKSHARE:
     case EXEC_OMP_SCAN:
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index ffe2db4881d..e3b1d1544aa 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -5543,6 +5543,8 @@  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_MASTER:
+	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
 	    case EXEC_OMP_PARALLEL_SECTIONS:
 
 	      in_omp_workshare = false;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 55fba04642a..2020ab4a503 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -267,7 +267,11 @@  enum gfc_statement
   ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_EVENT_POST,
   ST_EVENT_WAIT, ST_FAIL_IMAGE, ST_FORM_TEAM, ST_CHANGE_TEAM,
   ST_END_TEAM, ST_SYNC_TEAM,  ST_OMP_PARALLEL_MASTER,
-  ST_OMP_END_PARALLEL_MASTER, ST_NONE
+  ST_OMP_END_PARALLEL_MASTER, ST_OMP_PARALLEL_MASTER_TASKLOOP,
+  ST_OMP_END_PARALLEL_MASTER_TASKLOOP, ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
+  ST_OMP_END_PARALLEL_MASTER_TASKLOOP_SIMD, ST_OMP_MASTER_TASKLOOP,
+  ST_OMP_END_MASTER_TASKLOOP, ST_OMP_MASTER_TASKLOOP_SIMD,
+  ST_OMP_END_MASTER_TASKLOOP_SIMD, ST_NONE
 };
 
 /* Types of interfaces that we can have.  Assignment interfaces are
@@ -2711,7 +2715,9 @@  enum gfc_exec_op
   EXEC_OMP_TARGET_PARALLEL, EXEC_OMP_TARGET_PARALLEL_DO,
   EXEC_OMP_TARGET_PARALLEL_DO_SIMD, EXEC_OMP_TARGET_SIMD,
   EXEC_OMP_TASKLOOP, EXEC_OMP_TASKLOOP_SIMD, EXEC_OMP_SCAN, EXEC_OMP_DEPOBJ,
-  EXEC_OMP_PARALLEL_MASTER
+  EXEC_OMP_PARALLEL_MASTER, EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
+  EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD, EXEC_OMP_MASTER_TASKLOOP,
+  EXEC_OMP_MASTER_TASKLOOP_SIMD
 };
 
 typedef struct gfc_code
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 09c572324bc..bcedf8ef806 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -169,12 +169,16 @@  match gfc_match_omp_do (void);
 match gfc_match_omp_do_simd (void);
 match gfc_match_omp_flush (void);
 match gfc_match_omp_master (void);
+match gfc_match_omp_master_taskloop (void);
+match gfc_match_omp_master_taskloop_simd (void);
 match gfc_match_omp_ordered (void);
 match gfc_match_omp_ordered_depend (void);
 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_master (void);
+match gfc_match_omp_parallel_master_taskloop (void);
+match gfc_match_omp_parallel_master_taskloop_simd (void);
 match gfc_match_omp_parallel_sections (void);
 match gfc_match_omp_parallel_workshare (void);
 match gfc_match_omp_requires (void);
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 4ed6a0d64c8..9dba165f990 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -3995,6 +3995,22 @@  gfc_match_omp_parallel_master (void)
   return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
 }
 
+match
+gfc_match_omp_parallel_master_taskloop (void)
+{
+  return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
+		    (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
+		    & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
+}
+
+match
+gfc_match_omp_parallel_master_taskloop_simd (void)
+{
+  return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
+		    (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
+		     | OMP_SIMD_CLAUSES)
+		    & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
+}
 
 match
 gfc_match_omp_parallel_sections (void)
@@ -4429,8 +4445,7 @@  match
 gfc_match_omp_taskloop_simd (void)
 {
   return match_omp (EXEC_OMP_TASKLOOP_SIMD,
-		    (OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
-		    & ~(omp_mask (OMP_CLAUSE_REDUCTION)));
+		    OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
 }
 
 
@@ -4533,6 +4548,18 @@  gfc_match_omp_master (void)
   return MATCH_YES;
 }
 
+match
+gfc_match_omp_master_taskloop (void)
+{
+  return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
+}
+
+match
+gfc_match_omp_master_taskloop_simd (void)
+{
+  return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
+		    OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
+}
 
 match
 gfc_match_omp_ordered (void)
@@ -5073,6 +5100,16 @@  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_MASTER_TASKLOOP:
+	      ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
+	      break;
+
+	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+	      ok = (ifc == OMP_IF_PARALLEL
+		    || ifc == OMP_IF_TASKLOOP
+		    || ifc == OMP_IF_SIMD);
+	      break;
+
 	    case EXEC_OMP_SIMD:
 	    case EXEC_OMP_DO_SIMD:
 	    case EXEC_OMP_DISTRIBUTE_SIMD:
@@ -5085,10 +5122,12 @@  resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	      break;
 
 	    case EXEC_OMP_TASKLOOP:
+	    case EXEC_OMP_MASTER_TASKLOOP:
 	      ok = ifc == OMP_IF_TASKLOOP;
 	      break;
 
 	    case EXEC_OMP_TASKLOOP_SIMD:
+	    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
 	      ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
 	      break;
 
@@ -5848,11 +5887,16 @@  resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 			     n->sym->name, name, &n->where);
 		switch (list)
 		  {
-		  case OMP_LIST_REDUCTION_INSCAN:
 		  case OMP_LIST_REDUCTION_TASK:
-		    if (code && (code->op == EXEC_OMP_TASKLOOP
-				 || code->op == EXEC_OMP_TEAMS
-				 || code->op == EXEC_OMP_TEAMS_DISTRIBUTE))
+		    if (code
+			&& (code->op == EXEC_OMP_TASKLOOP
+			    || code->op == EXEC_OMP_TASKLOOP_SIMD
+			    || code->op == EXEC_OMP_MASTER_TASKLOOP
+			    || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
+			    || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
+			    || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
+			    || code->op == EXEC_OMP_TEAMS
+			    || code->op == EXEC_OMP_TEAMS_DISTRIBUTE))
 		      {
 			gfc_error ("Only DEFAULT permitted as reduction-"
 				   "modifier in REDUCTION clause at %L",
@@ -5863,6 +5907,7 @@  resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		  case OMP_LIST_REDUCTION:
 		  case OMP_LIST_IN_REDUCTION:
 		  case OMP_LIST_TASK_REDUCTION:
+		  case OMP_LIST_REDUCTION_INSCAN:
 		    switch (n->u.reduction_op)
 		      {
 		      case OMP_REDUCTION_PLUS:
@@ -6766,6 +6811,10 @@  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_MASTER_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+    case EXEC_OMP_MASTER_TASKLOOP:
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_TARGET_PARALLEL_DO:
     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
@@ -6909,6 +6958,18 @@  resolve_omp_do (gfc_code *code)
       name = "!$OMP PARALLEL DO SIMD";
       is_simd = true;
       break;
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+      name = "!$OMP PARALLEL MASTER TASKLOOP";
+      break;
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+      name = "!$OMP PARALLEL MASTER 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";
+      is_simd = true;
+      break;
     case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
     case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
@@ -7063,6 +7124,10 @@  omp_code_to_statement (gfc_code *code)
       return ST_OMP_PARALLEL;
     case EXEC_OMP_PARALLEL_MASTER:
       return ST_OMP_PARALLEL_MASTER;
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+      return ST_OMP_PARALLEL_MASTER_TASKLOOP;
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+      return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
     case EXEC_OMP_PARALLEL_SECTIONS:
       return ST_OMP_PARALLEL_SECTIONS;
     case EXEC_OMP_SECTIONS:
@@ -7073,6 +7138,10 @@  omp_code_to_statement (gfc_code *code)
       return ST_OMP_CRITICAL;
     case EXEC_OMP_MASTER:
       return ST_OMP_MASTER;
+    case EXEC_OMP_MASTER_TASKLOOP:
+      return ST_OMP_MASTER_TASKLOOP;
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
+      return ST_OMP_MASTER_TASKLOOP_SIMD;
     case EXEC_OMP_SINGLE:
       return ST_OMP_SINGLE;
     case EXEC_OMP_TASK:
@@ -7561,6 +7630,10 @@  gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
     case EXEC_OMP_DO_SIMD:
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+    case EXEC_OMP_MASTER_TASKLOOP:
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_SIMD:
     case EXEC_OMP_TARGET_PARALLEL_DO:
     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 6efb3fd5e7b..c44e23ccb62 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -920,11 +920,19 @@  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 master taskloop simd", gfc_match_omp_eos_error,
+	      ST_OMP_END_MASTER_TASKLOOP_SIMD);
+      matcho ("end master taskloop", gfc_match_omp_eos_error,
+	      ST_OMP_END_MASTER_TASKLOOP);
       matcho ("end master", gfc_match_omp_eos_error, ST_OMP_END_MASTER);
       matchs ("end ordered", gfc_match_omp_eos_error, ST_OMP_END_ORDERED);
       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 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,
+	      ST_OMP_END_PARALLEL_MASTER_TASKLOOP);
       matcho ("end parallel master", gfc_match_omp_eos_error,
 	      ST_OMP_END_PARALLEL_MASTER);
       matcho ("end parallel sections", gfc_match_omp_eos_error,
@@ -974,6 +982,10 @@  decode_omp_directive (void)
       matcho ("flush", gfc_match_omp_flush, ST_OMP_FLUSH);
       break;
     case 'm':
+      matcho ("master taskloop simd", gfc_match_omp_master_taskloop_simd,
+	      ST_OMP_MASTER_TASKLOOP_SIMD);
+      matcho ("master taskloop", gfc_match_omp_master_taskloop,
+	      ST_OMP_MASTER_TASKLOOP);
       matcho ("master", gfc_match_omp_master, ST_OMP_MASTER);
       break;
     case 'o':
@@ -992,6 +1004,12 @@  decode_omp_directive (void)
       matchs ("parallel do simd", gfc_match_omp_parallel_do_simd,
 	      ST_OMP_PARALLEL_DO_SIMD);
       matcho ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO);
+      matcho ("parallel master taskloop simd",
+	      gfc_match_omp_parallel_master_taskloop_simd,
+	      ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD);
+      matcho ("parallel master taskloop",
+	      gfc_match_omp_parallel_master_taskloop,
+	      ST_OMP_PARALLEL_MASTER_TASKLOOP);
       matcho ("parallel master", gfc_match_omp_parallel_master,
 	      ST_OMP_PARALLEL_MASTER);
       matcho ("parallel sections", gfc_match_omp_parallel_sections,
@@ -1610,8 +1628,11 @@  next_statement (void)
   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_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_SINGLE: \
+  case ST_OMP_CRITICAL: 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: \
   case ST_OMP_TASK: case ST_OMP_TASKGROUP: case ST_OMP_SIMD: \
@@ -2341,6 +2362,12 @@  gfc_ascii_statement (gfc_statement st)
     case ST_OMP_END_MASTER:
       p = "!$OMP END MASTER";
       break;
+    case ST_OMP_END_MASTER_TASKLOOP:
+      p = "!$OMP END MASTER TASKLOOP";
+      break;
+    case ST_OMP_END_MASTER_TASKLOOP_SIMD:
+      p = "!$OMP END MASTER TASKLOOP SIMD";
+      break;
     case ST_OMP_END_ORDERED:
       p = "!$OMP END ORDERED";
       break;
@@ -2356,6 +2383,12 @@  gfc_ascii_statement (gfc_statement st)
     case ST_OMP_END_PARALLEL_MASTER:
       p = "!$OMP END PARALLEL MASTER";
       break;
+    case ST_OMP_END_PARALLEL_MASTER_TASKLOOP:
+      p = "!$OMP END PARALLEL MASTER TASKLOOP";
+      break;
+    case ST_OMP_END_PARALLEL_MASTER_TASKLOOP_SIMD:
+      p = "!$OMP END PARALLEL MASTER TASKLOOP SIMD";
+      break;
     case ST_OMP_END_PARALLEL_SECTIONS:
       p = "!$OMP END PARALLEL SECTIONS";
       break;
@@ -2437,6 +2470,12 @@  gfc_ascii_statement (gfc_statement st)
     case ST_OMP_MASTER:
       p = "!$OMP MASTER";
       break;
+    case ST_OMP_MASTER_TASKLOOP:
+      p = "!$OMP MASTER TASKLOOP";
+      break;
+    case ST_OMP_MASTER_TASKLOOP_SIMD:
+      p = "!$OMP MASTER TASKLOOP SIMD";
+      break;
     case ST_OMP_ORDERED:
     case ST_OMP_ORDERED_DEPEND:
       p = "!$OMP ORDERED";
@@ -2453,6 +2492,12 @@  gfc_ascii_statement (gfc_statement st)
     case ST_OMP_PARALLEL_MASTER:
       p = "!$OMP PARALLEL MASTER";
       break;
+    case ST_OMP_PARALLEL_MASTER_TASKLOOP:
+      p = "!$OMP PARALLEL MASTER TASKLOOP";
+      break;
+    case ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+      p = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
+      break;
     case ST_OMP_PARALLEL_SECTIONS:
       p = "!$OMP PARALLEL SECTIONS";
       break;
@@ -5025,6 +5070,16 @@  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_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_MASTER_TASKLOOP:
+      omp_end_st = ST_OMP_END_PARALLEL_MASTER_TASKLOOP;
+      break;
+    case ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+      omp_end_st = ST_OMP_END_PARALLEL_MASTER_TASKLOOP_SIMD;
+      break;
     case ST_OMP_TEAMS_DISTRIBUTE:
       omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE;
       break;
@@ -5268,6 +5323,12 @@  parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
     case ST_OMP_PARALLEL_MASTER:
       omp_end_st = ST_OMP_END_PARALLEL_MASTER;
       break;
+    case ST_OMP_PARALLEL_MASTER_TASKLOOP:
+      omp_end_st = ST_OMP_END_PARALLEL_MASTER_TASKLOOP;
+      break;
+    case ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+      omp_end_st = ST_OMP_END_PARALLEL_MASTER_TASKLOOP_SIMD;
+      break;
     case ST_OMP_PARALLEL_SECTIONS:
       omp_end_st = ST_OMP_END_PARALLEL_SECTIONS;
       break;
@@ -5283,6 +5344,12 @@  parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
     case ST_OMP_MASTER:
       omp_end_st = ST_OMP_END_MASTER;
       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_SINGLE:
       omp_end_st = ST_OMP_END_SINGLE;
       break;
@@ -5624,6 +5691,10 @@  parse_executable (gfc_statement st)
 	case ST_OMP_DO_SIMD:
 	case ST_OMP_PARALLEL_DO:
 	case ST_OMP_PARALLEL_DO_SIMD:
+	case ST_OMP_PARALLEL_MASTER_TASKLOOP:
+	case ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
+	case ST_OMP_MASTER_TASKLOOP:
+	case ST_OMP_MASTER_TASKLOOP_SIMD:
 	case ST_OMP_SIMD:
 	case ST_OMP_TARGET_PARALLEL_DO:
 	case ST_OMP_TARGET_PARALLEL_DO_SIMD:
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 747516fbc1d..fed6dce3d98 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -10798,11 +10798,15 @@  gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
 	case EXEC_OMP_DO:
 	case EXEC_OMP_DO_SIMD:
 	case EXEC_OMP_MASTER:
+	case EXEC_OMP_MASTER_TASKLOOP:
+	case EXEC_OMP_MASTER_TASKLOOP_SIMD:
 	case EXEC_OMP_ORDERED:
 	case EXEC_OMP_PARALLEL:
 	case EXEC_OMP_PARALLEL_DO:
 	case EXEC_OMP_PARALLEL_DO_SIMD:
 	case EXEC_OMP_PARALLEL_MASTER:
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
 	case EXEC_OMP_PARALLEL_SECTIONS:
 	case EXEC_OMP_PARALLEL_WORKSHARE:
 	case EXEC_OMP_SECTIONS:
@@ -11765,6 +11769,8 @@  gfc_resolve_code (gfc_code *code, gfc_namespace *ns)
 	    case EXEC_OMP_PARALLEL_DO:
 	    case EXEC_OMP_PARALLEL_DO_SIMD:
 	    case EXEC_OMP_PARALLEL_MASTER:
+	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
 	    case EXEC_OMP_PARALLEL_SECTIONS:
 	    case EXEC_OMP_TARGET_PARALLEL:
 	    case EXEC_OMP_TARGET_PARALLEL_DO:
@@ -12214,6 +12220,8 @@  start:
 	case EXEC_OMP_DO:
 	case EXEC_OMP_DO_SIMD:
 	case EXEC_OMP_MASTER:
+	case EXEC_OMP_MASTER_TASKLOOP:
+	case EXEC_OMP_MASTER_TASKLOOP_SIMD:
 	case EXEC_OMP_ORDERED:
 	case EXEC_OMP_SCAN:
 	case EXEC_OMP_SECTIONS:
@@ -12252,6 +12260,8 @@  start:
 	case EXEC_OMP_PARALLEL_DO:
 	case EXEC_OMP_PARALLEL_DO_SIMD:
 	case EXEC_OMP_PARALLEL_MASTER:
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
 	case EXEC_OMP_PARALLEL_SECTIONS:
 	case EXEC_OMP_PARALLEL_WORKSHARE:
 	  omp_workshare_save = omp_workshare_flag;
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index 7d0e2c14731..9f6fe49db02 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -226,11 +226,15 @@  gfc_free_statement (gfc_code *p)
     case EXEC_OMP_DO:
     case EXEC_OMP_DO_SIMD:
     case EXEC_OMP_END_SINGLE:
+    case EXEC_OMP_MASTER_TASKLOOP:
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_ORDERED:
     case EXEC_OMP_PARALLEL:
     case EXEC_OMP_PARALLEL_DO:
     case EXEC_OMP_PARALLEL_DO_SIMD:
     case EXEC_OMP_PARALLEL_MASTER:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_PARALLEL_SECTIONS:
     case EXEC_OMP_PARALLEL_WORKSHARE:
     case EXEC_OMP_SCAN:
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 7ea7aa37efd..2917d3d058b 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -5380,6 +5380,14 @@  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_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_MASTER_TASKLOOP_SIMD:
+      mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
+      innermost = GFC_OMP_SPLIT_SIMD;
+      break;
     case EXEC_OMP_SIMD:
       innermost = GFC_OMP_SPLIT_SIMD;
       break;
@@ -5427,9 +5435,11 @@  gfc_split_omp_clauses (gfc_code *code,
 	     | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
       innermost = GFC_OMP_SPLIT_SIMD;
       break;
+    case EXEC_OMP_MASTER_TASKLOOP:
     case EXEC_OMP_TASKLOOP:
       innermost = GFC_OMP_SPLIT_TASKLOOP;
       break;
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
     case EXEC_OMP_TASKLOOP_SIMD:
       mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
       innermost = GFC_OMP_SPLIT_SIMD;
@@ -5820,28 +5830,6 @@  gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
   return gfc_finish_block (&block);
 }
 
-static tree
-gfc_trans_omp_parallel_master (gfc_code *code)
-{
-  stmtblock_t block;
-  tree stmt, omp_clauses;
-
-  gfc_start_block (&block);
-  omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
-				       code->loc);
-  pushlevel ();
-  stmt = gfc_trans_omp_master (code);
-  if (TREE_CODE (stmt) != BIND_EXPR)
-    stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
-  else
-    poplevel (0, 0);
-  stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
-		     void_type_node, stmt, omp_clauses);
-  OMP_PARALLEL_COMBINED (stmt) = 1;
-  gfc_add_expr_to_block (&block, stmt);
-  return gfc_finish_block (&block);
-}
-
 static tree
 gfc_trans_omp_parallel_sections (gfc_code *code)
 {
@@ -6217,7 +6205,7 @@  gfc_trans_omp_target (gfc_code *code)
 }
 
 static tree
-gfc_trans_omp_taskloop (gfc_code *code)
+gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
 {
   stmtblock_t block;
   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
@@ -6229,7 +6217,7 @@  gfc_trans_omp_taskloop (gfc_code *code)
     omp_clauses
       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
 			       code->loc);
-  switch (code->op)
+  switch (op)
     {
     case EXEC_OMP_TASKLOOP:
       /* This is handled in gfc_trans_omp_do.  */
@@ -6258,6 +6246,75 @@  gfc_trans_omp_taskloop (gfc_code *code)
   return gfc_finish_block (&block);
 }
 
+static tree
+gfc_trans_omp_master_taskloop (gfc_code *code, gfc_exec_op op)
+{
+  stmtblock_t block;
+  tree stmt;
+
+  gfc_start_block (&block);
+  pushlevel ();
+  if (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);
+      stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
+			       op != code->op
+			       ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
+			       : code->ext.omp_clauses, NULL);
+    }
+  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);
+  return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_parallel_master (gfc_code *code)
+{
+  stmtblock_t block;
+  tree stmt, omp_clauses;
+  gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
+
+  if (code->op != EXEC_OMP_PARALLEL_MASTER)
+    gfc_split_omp_clauses (code, clausesa);
+
+  gfc_start_block (&block);
+  omp_clauses = gfc_trans_omp_clauses (&block,
+				       code->op == EXEC_OMP_PARALLEL_MASTER
+				       ? code->ext.omp_clauses
+				       : &clausesa[GFC_OMP_SPLIT_PARALLEL],
+				       code->loc);
+  pushlevel ();
+  if (code->op == EXEC_OMP_PARALLEL_MASTER)
+    stmt = gfc_trans_omp_master (code);
+  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);
+    }
+  if (TREE_CODE (stmt) != BIND_EXPR)
+    stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+  else
+    poplevel (0, 0);
+  stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
+		     void_type_node, stmt, omp_clauses);
+  OMP_PARALLEL_COMBINED (stmt) = 1;
+  gfc_add_expr_to_block (&block, stmt);
+  return gfc_finish_block (&block);
+}
+
 static tree
 gfc_trans_omp_target_data (gfc_code *code)
 {
@@ -6568,6 +6625,9 @@  gfc_trans_omp_directive (gfc_code *code)
       return gfc_trans_omp_flush (code);
     case EXEC_OMP_MASTER:
       return gfc_trans_omp_master (code);
+    case EXEC_OMP_MASTER_TASKLOOP:
+    case EXEC_OMP_MASTER_TASKLOOP_SIMD:
+      return gfc_trans_omp_master_taskloop (code, code->op);
     case EXEC_OMP_ORDERED:
       return gfc_trans_omp_ordered (code);
     case EXEC_OMP_PARALLEL:
@@ -6577,6 +6637,8 @@  gfc_trans_omp_directive (gfc_code *code)
     case EXEC_OMP_PARALLEL_DO_SIMD:
       return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
     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);
     case EXEC_OMP_PARALLEL_SECTIONS:
       return gfc_trans_omp_parallel_sections (code);
@@ -6610,7 +6672,7 @@  gfc_trans_omp_directive (gfc_code *code)
     case EXEC_OMP_TASKGROUP:
       return gfc_trans_omp_taskgroup (code);
     case EXEC_OMP_TASKLOOP_SIMD:
-      return gfc_trans_omp_taskloop (code);
+      return gfc_trans_omp_taskloop (code, code->op);
     case EXEC_OMP_TASKWAIT:
       return gfc_trans_omp_taskwait (code);
     case EXEC_OMP_TASKYIELD:
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 9f296bd8c03..cbbfcd9d1bc 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -2170,11 +2170,15 @@  trans_code (gfc_code * code, tree cond)
 	case EXEC_OMP_DO_SIMD:
 	case EXEC_OMP_FLUSH:
 	case EXEC_OMP_MASTER:
+	case EXEC_OMP_MASTER_TASKLOOP:
+	case EXEC_OMP_MASTER_TASKLOOP_SIMD:
 	case EXEC_OMP_ORDERED:
 	case EXEC_OMP_PARALLEL:
 	case EXEC_OMP_PARALLEL_DO:
 	case EXEC_OMP_PARALLEL_DO_SIMD:
 	case EXEC_OMP_PARALLEL_MASTER:
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
 	case EXEC_OMP_PARALLEL_SECTIONS:
 	case EXEC_OMP_PARALLEL_WORKSHARE:
 	case EXEC_OMP_SECTIONS:
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90
new file mode 100644
index 00000000000..ce43dfb8ccd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90
@@ -0,0 +1,139 @@ 
+! PR middle-end/99928
+! { dg-do compile }
+! { dg-options "-fopenmp -fdump-tree-gimple" }
+
+module m
+  implicit none
+  integer :: l00, l01, l02, l03, l04, l07, l08, l09
+  integer :: l10, l11
+
+contains
+
+subroutine bar ()
+  integer :: l05, l06
+  integer :: i
+  l05 = 0; l06 = 0
+  ! { dg-final { scan-tree-dump "omp for\[^\n\r]*firstprivate\\(l00\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(l00\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l00\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l00\\)" "gimple" } }
+  !$omp do simd firstprivate (l00) lastprivate (l00)
+  do i = 1, 64
+    l00 = i
+  end do
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l01\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l01\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l01\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l01\\)" "gimple" } }
+  !$omp master taskloop firstprivate (l01) lastprivate (l01)
+  do i = 1, 64
+    l01 = i
+  end do
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l02\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l02\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l02\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l02\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l02\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l02\\)" "gimple" } }
+  !$omp master taskloop simd firstprivate (l02) lastprivate (l02)
+  do i = 1, 64
+    l02 = i
+  end do
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l03\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l03\\)" "gimple" } } ! FIXME. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } ! FIXME. 
+  !$omp parallel do firstprivate (l03) lastprivate (l03)
+  do i = 1, 64
+    l03 = i
+  end do
+  !$omp end parallel do
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } ! FIXME. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } ! FIXME. 
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l04\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l04\\)" "gimple" } }
+  !$omp parallel do simd firstprivate (l04) lastprivate (l04)
+  do i = 1, 64
+    l04 = i
+  end do
+  !$omp end parallel do simd
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l05\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l05\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l05\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l05\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l05\\)" "gimple" { xfail *-*-* } } }
+  !$omp parallel master taskloop firstprivate (l05) lastprivate (l05)
+  do i = 1, 64
+    l05 = i
+  end do
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l06\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l06\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l06\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l06\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l06\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l06\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l06\\)" "gimple" } }
+  !$omp parallel master taskloop simd firstprivate (l06) lastprivate (l06)
+  do i = 1, 64
+    l06 = i
+  end do
+  !$omp end parallel master taskloop simd
+  ! FIXME: OpenMP 5.0/5.1 broken here, conceptually it should be shared on parallel and
+  ! firstprivate+lastprivate on sections, in GCC implementation we put firstprivate+lastprivate
+  ! on parallel for historic reasons, but OpenMP 5.0/5.1 mistakenly say firstprivate
+  ! should be on parallel and lastprivate on sections. 
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l07\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l07\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*firstprivate\\(l07\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*lastprivate\\(l07\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp section \[^\n\r]*firstprivate\\(l07\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp section \[^\n\r]*lastprivate\\(l07\\)" "gimple" } }
+  !$omp parallel sections firstprivate (l07) lastprivate (l07)
+    l07 = 1
+    !$omp section
+    l07 = 2
+  !$omp end parallel sections
+  ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l08" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l08\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } ! FIXME. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } ! FIXME. 
+  !$omp target parallel do firstprivate (l08) lastprivate (l08)
+  do i = 1, 64
+    l08 = i
+  end do
+  !$omp end target parallel do
+  ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l09" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l09\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } ! FIXME: This should be on for instead. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } ! FIXME. 
+  ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } ! FIXME. 
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l09\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l09\\)" "gimple" } }
+  !$omp target parallel do simd firstprivate (l09) lastprivate (l09)
+  do i = 1, 64
+    l09 = i
+  end do
+  ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l10" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l10\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l10\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l10\\)" "gimple" } }
+  !$omp target simd firstprivate (l10) lastprivate (l10)
+  do i = 1, 64
+    l10 = i
+  end do
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l11\\)" "gimple" { xfail *-*-* } } }
+  ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l11\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l11\\)" "gimple" } }
+  ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l11\\)" "gimple" } }
+ !$omp taskloop simd firstprivate (l11) lastprivate (l11)
+  do i = 1, 64
+    l11 = i
+  end do
+  !$omp end taskloop simd
+end
+end module m
diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction5.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction5.f90
index 032703d3b81..44f89d84c78 100644
--- a/gcc/testsuite/gfortran.dg/gomp/reduction5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/reduction5.f90
@@ -22,8 +22,7 @@  end do
 
 !$omp taskloop reduction(inscan,+:a) in_reduction(+:b) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
   ! { dg-error "34: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
-  ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause" "" { target *-*-* } .-2 }
-  ! { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" "" { target *-*-* } .-3 }
+  ! { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" "" { target *-*-* } .-2 }
 do i=1,10
   a = a + 1
 end do
@@ -34,7 +33,6 @@  do i=1,10
 end do
 
 !$omp teams reduction(inscan,+:b) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
-  ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause" "" { target *-*-* } .-1 }
   a = a + 1
 !$omp end teams
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-1.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-1.f90
index 8c879fd98b9..61d89259c48 100644
--- a/gcc/testsuite/gfortran.dg/gomp/scan-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-1.f90
@@ -100,7 +100,7 @@  subroutine f3 (c, d)
   use m
   implicit none
   integer i, c(64), d(64)
-  !$omp teams reduction (inscan, +: a)  ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause at" }
+  !$omp teams reduction (inscan, +: a)
     ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
     ! ...
   !$omp end teams
@@ -135,7 +135,7 @@  subroutine f4 (c, d)
   use m
   implicit none
   integer i, c(64), d(64)
-  !$omp taskloop reduction (inscan, +: a)  ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause" }
+  !$omp taskloop reduction (inscan, +: a)
   ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
   do i = 1, 64
     d(i) = a
diff --git a/gcc/testsuite/gfortran.dg/gomp/taskloop-1.f90 b/gcc/testsuite/gfortran.dg/gomp/taskloop-1.f90
new file mode 100644
index 00000000000..7060a7a5c96
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/taskloop-1.f90
@@ -0,0 +1,126 @@ 
+module m
+  implicit none
+  integer :: t
+  !$omp threadprivate (t)
+  integer :: f, l, ll, r, r2
+  !$omp declare target to(f, l, ll, r, r2)
+end module m
+
+subroutine foo(fi, p, pp, g, s, nta, nth, ntm, i1, i2, i3, q)
+  use m
+  implicit none
+  integer, value :: p, pp, g, s, nta, nth, ntm
+  logical, value :: fi, i1, i2, i3
+  integer, pointer :: q(:)
+  integer :: i
+
+  !$omp taskgroup task_reduction(+:r2) !allocate (r2)
+  !$omp taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) &
+  !$omp& 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) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp end taskgroup
+
+  !$omp taskgroup task_reduction(+:r) !allocate (r)
+  !$omp taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) &
+  !$omp& collapse(1) untied if(i1) final(fi) mergeable nogroup priority (pp) &
+  !$omp& safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) nontemporal(ntm) &
+  !$omp& order(concurrent) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp taskwait
+
+  !$omp taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) &
+  !$omp& collapse(1) if(taskloop: i1) final(fi) priority (pp) &
+  !$omp& safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) if (simd: i3) nontemporal(ntm) &
+  !$omp& order(concurrent) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp end taskgroup
+
+  !$omp taskgroup task_reduction (+:r2) !allocate (r2)
+  !$omp master taskloop &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) &
+  !$omp& collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) &
+  !$omp& reduction(default, +:r) in_reduction(+:r2) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp end taskgroup
+
+  !$omp taskgroup task_reduction (+:r2) !allocate (r2)
+  !$omp master taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) &
+  !$omp& 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) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp end taskgroup
+
+  !$omp parallel master taskloop &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) &
+  !$omp& 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) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+
+  !$omp parallel master taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) &
+  !$omp& 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) &
+  !$omp& if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) &
+  !$omp& order(concurrent) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+
+  !$omp taskgroup task_reduction (+:r2) !allocate (r2)
+  !$omp master taskloop &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) &
+  !$omp& collapse(1) untied if(i1) final(fi) mergeable priority (pp) &
+  !$omp& reduction(default, +:r) in_reduction(+:r2)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp end taskgroup
+
+  !$omp taskgroup task_reduction (+:r2) !allocate (r2)
+  !$omp master taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) &
+  !$omp& collapse(1) untied if(i1) 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) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+  !$omp end taskgroup
+
+  !$omp parallel master taskloop &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) &
+  !$omp& collapse(1) untied if(i1) final(fi) mergeable priority (pp) &
+  !$omp& reduction(default, +:r) num_threads (nth) proc_bind(spread) copyin(t) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+
+  !$omp parallel master taskloop simd &
+  !$omp& private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) &
+  !$omp& collapse(1) untied if(i1) final(fi) mergeable priority (pp) &
+  !$omp& safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) &
+  !$omp& nontemporal(ntm) num_threads (nth) proc_bind(spread) copyin(t) &
+  !$omp& order(concurrent) !allocate (f)
+  do i = 1, 64
+    ll = ll + 1
+  end do
+end