diff mbox

[gomp4.5] Parsing of most of OpenMP 4.5 clauses

Message ID 20160506193256.GC1909@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek May 6, 2016, 7:32 p.m. UTC
Hi!

This patch adds parsing of most of the OpenMP 4.5 clause changes,
though doesn't do anything during resolve or later with them yet.
Missing is still depend clause parsing changes (sink and source) and
link and to clause for declare target construct.

2016-05-06  Jakub Jelinek  <jakub@redhat.com>

	* gfortran.h (enum gfc_omp_map_op): Add OMP_MAP_RELEASE,
	OMP_MAP_ALWAYS_TO, OMP_MAP_ALWAYS_FROM and OMP_MAP_ALWAYS_TOFROM.
	(OMP_LIST_IS_DEVICE_PTR, OMP_LIST_USE_DEVICE_PTR): New.
	(enum gfc_omp_if_kind): New.
	(struct gfc_omp_clauses): Add orderedc, defaultmap, nogroup,
	sched_simd, sched_monotonic, sched_nonmonotonic, simd, threads,
	grainsize, hint, num_tasks, priority and if_exprs fields.
	* openmp.c (gfc_free_omp_clauses): Free grainsize, hint, num_tasks,
	priority and if_exprs.
	(enum omp_mask1): Add OMP_CLAUSE_DEFAULTMAP, OMP_CLAUSE_GRAINSIZE,
	OMP_CLAUSE_HINT, OMP_CLAUSE_IS_DEVICE_PTR, OMP_CLAUSE_LINK,
	OMP_CLAUSE_NOGROUP, OMP_CLAUSE_NUM_TASKS, OMP_CLAUSE_PRIORITY,
	OMP_CLAUSE_SIMD, OMP_CLAUSE_THREADS, OMP_CLAUSE_USE_DEVICE_PTR
	and OMP_CLAUSE_NOWAIT.
	(enum omp_mask2): Remove OMP_CLAUSE_OACC_DEVICE and OMP_CLAUSE_LINK.
	(gfc_match_omp_clauses): Move delete clause handling to where it
	alphabetically belongs.  Parse defaultmap, grainsize, hint,
	is_device_ptr, nogroup, nowait, num_tasks, priority, simd, threads
	and use_device_ptr clauses.  Parse if clause modifier.  Parse map
	clause always modifier, and release and delete kinds.  Parse ordered
	clause with argument.  Parse schedule clause modifiers.  Differentiate
	device clause parsing based on openacc flag.  Guard link clause
	parsing with openacc flag.
	(OACC_UPDATE_CLAUSES): Replace OMP_CLAUSE_OACC_DEVICE with
	OMP_CLAUSE_DEVICE.
	(OMP_TASK_CLAUSES): Add OMP_CLAUSE_PRIORITY.
	(OMP_TARGET_CLAUSES): Add OMP_CLAUSE_DEPEND, OMP_CLAUSE_NOWAIT,
	OMP_CLAUSE_PRIVATE, OMP_CLAUSE_FIRSTPRIVATE, OMP_CLAUSE_DEFAULTMAP
	and OMP_CLAUSE_IS_DEVICE_PTR.     
	(OMP_TARGET_DATA_CLAUSES): Add OMP_CLAUSE_USE_DEVICE_PTR.
	(OMP_TARGET_UPDATE_CLAUSES): Add OMP_CLAUSE_DEPEND and
	OMP_CLAUSE_NOWAIT.
	(resolve_omp_clauses): Add dummy OMP_LIST_IS_DEVICE_PTR and
	OMP_LIST_USE_DEVICE_PTR cases.
	* frontend-passes.c (gfc_code_walker): Handle new OpenMP 4.5
	expressions.
	* dump-parse-tree.c (show_omp_clauses): Adjust for OpenMP 4.5
	clause changes.  


	Jakub

Comments

Paul Richard Thomas May 7, 2016, 6:42 p.m. UTC | #1
Dear Jakub,

As you might have noticed, I am forced to spend a couple of months out
from gfortran support in order to move from France back to the UK. I
am therefore dealing very sporadically with patches. Since we seem to
have entered a phase where all the other gfortran contributors have
gone quiet, I suggest that where omp patches are concerned you commit
when you are satisfied that all is well.

I have taken a rapid look through your patch and cannot see anything
to object to. OK by me for trunk.

Cheers

Paul

On 6 May 2016 at 21:32, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> This patch adds parsing of most of the OpenMP 4.5 clause changes,
> though doesn't do anything during resolve or later with them yet.
> Missing is still depend clause parsing changes (sink and source) and
> link and to clause for declare target construct.
>
> 2016-05-06  Jakub Jelinek  <jakub@redhat.com>
>
>         * gfortran.h (enum gfc_omp_map_op): Add OMP_MAP_RELEASE,
>         OMP_MAP_ALWAYS_TO, OMP_MAP_ALWAYS_FROM and OMP_MAP_ALWAYS_TOFROM.
>         (OMP_LIST_IS_DEVICE_PTR, OMP_LIST_USE_DEVICE_PTR): New.
>         (enum gfc_omp_if_kind): New.
>         (struct gfc_omp_clauses): Add orderedc, defaultmap, nogroup,
>         sched_simd, sched_monotonic, sched_nonmonotonic, simd, threads,
>         grainsize, hint, num_tasks, priority and if_exprs fields.
>         * openmp.c (gfc_free_omp_clauses): Free grainsize, hint, num_tasks,
>         priority and if_exprs.
>         (enum omp_mask1): Add OMP_CLAUSE_DEFAULTMAP, OMP_CLAUSE_GRAINSIZE,
>         OMP_CLAUSE_HINT, OMP_CLAUSE_IS_DEVICE_PTR, OMP_CLAUSE_LINK,
>         OMP_CLAUSE_NOGROUP, OMP_CLAUSE_NUM_TASKS, OMP_CLAUSE_PRIORITY,
>         OMP_CLAUSE_SIMD, OMP_CLAUSE_THREADS, OMP_CLAUSE_USE_DEVICE_PTR
>         and OMP_CLAUSE_NOWAIT.
>         (enum omp_mask2): Remove OMP_CLAUSE_OACC_DEVICE and OMP_CLAUSE_LINK.
>         (gfc_match_omp_clauses): Move delete clause handling to where it
>         alphabetically belongs.  Parse defaultmap, grainsize, hint,
>         is_device_ptr, nogroup, nowait, num_tasks, priority, simd, threads
>         and use_device_ptr clauses.  Parse if clause modifier.  Parse map
>         clause always modifier, and release and delete kinds.  Parse ordered
>         clause with argument.  Parse schedule clause modifiers.  Differentiate
>         device clause parsing based on openacc flag.  Guard link clause
>         parsing with openacc flag.
>         (OACC_UPDATE_CLAUSES): Replace OMP_CLAUSE_OACC_DEVICE with
>         OMP_CLAUSE_DEVICE.
>         (OMP_TASK_CLAUSES): Add OMP_CLAUSE_PRIORITY.
>         (OMP_TARGET_CLAUSES): Add OMP_CLAUSE_DEPEND, OMP_CLAUSE_NOWAIT,
>         OMP_CLAUSE_PRIVATE, OMP_CLAUSE_FIRSTPRIVATE, OMP_CLAUSE_DEFAULTMAP
>         and OMP_CLAUSE_IS_DEVICE_PTR.
>         (OMP_TARGET_DATA_CLAUSES): Add OMP_CLAUSE_USE_DEVICE_PTR.
>         (OMP_TARGET_UPDATE_CLAUSES): Add OMP_CLAUSE_DEPEND and
>         OMP_CLAUSE_NOWAIT.
>         (resolve_omp_clauses): Add dummy OMP_LIST_IS_DEVICE_PTR and
>         OMP_LIST_USE_DEVICE_PTR cases.
>         * frontend-passes.c (gfc_code_walker): Handle new OpenMP 4.5
>         expressions.
>         * dump-parse-tree.c (show_omp_clauses): Adjust for OpenMP 4.5
>         clause changes.
>
> --- gcc/fortran/gfortran.h.jj   2016-05-04 18:37:26.000000000 +0200
> +++ gcc/fortran/gfortran.h      2016-05-06 19:01:13.813857650 +0200
> @@ -1120,7 +1120,11 @@ enum gfc_omp_map_op
>    OMP_MAP_FORCE_PRESENT,
>    OMP_MAP_FORCE_DEVICEPTR,
>    OMP_MAP_DEVICE_RESIDENT,
> -  OMP_MAP_LINK
> +  OMP_MAP_LINK,
> +  OMP_MAP_RELEASE,
> +  OMP_MAP_ALWAYS_TO,
> +  OMP_MAP_ALWAYS_FROM,
> +  OMP_MAP_ALWAYS_TOFROM
>  };
>
>  /* For use in OpenMP clauses in case we need extra information
> @@ -1165,6 +1169,8 @@ enum
>    OMP_LIST_LINK,
>    OMP_LIST_USE_DEVICE,
>    OMP_LIST_CACHE,
> +  OMP_LIST_IS_DEVICE_PTR,
> +  OMP_LIST_USE_DEVICE_PTR,
>    OMP_LIST_NUM
>  };
>
> @@ -1207,6 +1213,19 @@ enum gfc_omp_cancel_kind
>    OMP_CANCEL_TASKGROUP
>  };
>
> +enum gfc_omp_if_kind
> +{
> +  OMP_IF_PARALLEL,
> +  OMP_IF_TASK,
> +  OMP_IF_TASKLOOP,
> +  OMP_IF_TARGET,
> +  OMP_IF_TARGET_DATA,
> +  OMP_IF_TARGET_UPDATE,
> +  OMP_IF_TARGET_ENTER_DATA,
> +  OMP_IF_TARGET_EXIT_DATA,
> +  OMP_IF_LAST
> +};
> +
>  typedef struct gfc_omp_clauses
>  {
>    struct gfc_expr *if_expr;
> @@ -1216,9 +1235,11 @@ typedef struct gfc_omp_clauses
>    enum gfc_omp_sched_kind sched_kind;
>    struct gfc_expr *chunk_size;
>    enum gfc_omp_default_sharing default_sharing;
> -  int collapse;
> +  int collapse, orderedc;
>    bool nowait, ordered, untied, mergeable;
> -  bool inbranch, notinbranch;
> +  bool inbranch, notinbranch, defaultmap, nogroup;
> +  bool sched_simd, sched_monotonic, sched_nonmonotonic;
> +  bool simd, threads;
>    enum gfc_omp_cancel_kind cancel;
>    enum gfc_omp_proc_bind_kind proc_bind;
>    struct gfc_expr *safelen_expr;
> @@ -1226,6 +1247,11 @@ typedef struct gfc_omp_clauses
>    struct gfc_expr *num_teams;
>    struct gfc_expr *device;
>    struct gfc_expr *thread_limit;
> +  struct gfc_expr *grainsize;
> +  struct gfc_expr *hint;
> +  struct gfc_expr *num_tasks;
> +  struct gfc_expr *priority;
> +  struct gfc_expr *if_exprs[OMP_IF_LAST];
>    enum gfc_omp_sched_kind dist_sched_kind;
>    struct gfc_expr *dist_chunk_size;
>
> --- gcc/fortran/openmp.c.jj     2016-05-06 11:25:50.322794151 +0200
> +++ gcc/fortran/openmp.c        2016-05-06 19:00:17.642600199 +0200
> @@ -76,6 +76,12 @@ gfc_free_omp_clauses (gfc_omp_clauses *c
>    gfc_free_expr (c->device);
>    gfc_free_expr (c->thread_limit);
>    gfc_free_expr (c->dist_chunk_size);
> +  gfc_free_expr (c->grainsize);
> +  gfc_free_expr (c->hint);
> +  gfc_free_expr (c->num_tasks);
> +  gfc_free_expr (c->priority);
> +  for (i = 0; i < OMP_IF_LAST; i++)
> +    gfc_free_expr (c->if_exprs[i]);
>    gfc_free_expr (c->async_expr);
>    gfc_free_expr (c->gang_num_expr);
>    gfc_free_expr (c->gang_static_expr);
> @@ -574,6 +580,18 @@ enum omp_mask1
>    OMP_CLAUSE_NUM_TEAMS,
>    OMP_CLAUSE_THREAD_LIMIT,
>    OMP_CLAUSE_DIST_SCHEDULE,
> +  OMP_CLAUSE_DEFAULTMAP,
> +  OMP_CLAUSE_GRAINSIZE,
> +  OMP_CLAUSE_HINT,
> +  OMP_CLAUSE_IS_DEVICE_PTR,
> +  OMP_CLAUSE_LINK,
> +  OMP_CLAUSE_NOGROUP,
> +  OMP_CLAUSE_NUM_TASKS,
> +  OMP_CLAUSE_PRIORITY,
> +  OMP_CLAUSE_SIMD,
> +  OMP_CLAUSE_THREADS,
> +  OMP_CLAUSE_USE_DEVICE_PTR,
> +  OMP_CLAUSE_NOWAIT,
>    /* This must come last.  */
>    OMP_MASK1_LAST
>  };
> @@ -602,12 +620,10 @@ enum omp_mask2
>    OMP_CLAUSE_USE_DEVICE,
>    OMP_CLAUSE_DEVICE_RESIDENT,
>    OMP_CLAUSE_HOST_SELF,
> -  OMP_CLAUSE_OACC_DEVICE,
>    OMP_CLAUSE_WAIT,
>    OMP_CLAUSE_DELETE,
>    OMP_CLAUSE_AUTO,
>    OMP_CLAUSE_TILE,
> -  OMP_CLAUSE_LINK,
>    /* This must come last.  */
>    OMP_MASK2_LAST
>  };
> @@ -867,11 +883,6 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>             continue;
>           break;
>         case 'd':
> -         if ((mask & OMP_CLAUSE_DELETE)
> -             && gfc_match ("delete ( ") == MATCH_YES
> -             && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
> -                                          OMP_MAP_DELETE))
> -           continue;
>           if ((mask & OMP_CLAUSE_DEFAULT)
>               && c->default_sharing == OMP_DEFAULT_UNKNOWN)
>             {
> @@ -888,6 +899,18 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
>                 continue;
>             }
> +         if ((mask & OMP_CLAUSE_DEFAULTMAP)
> +             && !c->defaultmap
> +             && gfc_match ("defaultmap ( tofrom : scalar )") == MATCH_YES)
> +           {
> +             c->defaultmap = true;
> +             continue;
> +           }
> +         if ((mask & OMP_CLAUSE_DELETE)
> +             && gfc_match ("delete ( ") == MATCH_YES
> +             && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
> +                                          OMP_MAP_DELETE))
> +           continue;
>           if ((mask & OMP_CLAUSE_DEPEND)
>               && gfc_match ("depend ( ") == MATCH_YES)
>             {
> @@ -917,10 +940,12 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>                 gfc_current_locus = old_loc;
>             }
>           if ((mask & OMP_CLAUSE_DEVICE)
> +             && !openacc
>               && c->device == NULL
>               && gfc_match ("device ( %e )", &c->device) == MATCH_YES)
>             continue;
> -         if ((mask & OMP_CLAUSE_OACC_DEVICE)
> +         if ((mask & OMP_CLAUSE_DEVICE)
> +             && openacc
>               && gfc_match ("device ( ") == MATCH_YES
>               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
>                                            OMP_MAP_FORCE_TO))
> @@ -990,8 +1015,16 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>                 needs_space = true;
>               continue;
>             }
> +         if ((mask & OMP_CLAUSE_GRAINSIZE)
> +             && c->grainsize == NULL
> +             && gfc_match ("grainsize ( %e )", &c->grainsize) == MATCH_YES)
> +           continue;
>           break;
>         case 'h':
> +         if ((mask & OMP_CLAUSE_HINT)
> +             && c->hint == NULL
> +             && gfc_match ("hint ( %e )", &c->hint) == MATCH_YES)
> +           continue;
>           if ((mask & OMP_CLAUSE_HOST_SELF)
>               && gfc_match ("host ( ") == MATCH_YES
>               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
> @@ -1001,8 +1034,32 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>         case 'i':
>           if ((mask & OMP_CLAUSE_IF)
>               && c->if_expr == NULL
> -             && gfc_match ("if ( %e )", &c->if_expr) == MATCH_YES)
> -           continue;
> +             && gfc_match ("if ( ") == MATCH_YES)
> +           {
> +             if (gfc_match ("%e )", &c->if_expr) == MATCH_YES)
> +               continue;
> +             if (!openacc)
> +               {
> +                 /* This should match the enum gfc_omp_if_kind order.  */
> +                 static const char *ifs[OMP_IF_LAST] = {
> +                   " parallel : %e )",
> +                   " task : %e )",
> +                   " taskloop : %e )",
> +                   " target : %e )",
> +                   " target data : %e )",
> +                   " target update : %e )",
> +                   " target enter data : %e )",
> +                   " target exit data : %e )" };
> +                 int i;
> +                 for (i = 0; i < OMP_IF_LAST; i++)
> +                   if (c->if_exprs[i] == NULL
> +                       && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
> +                     break;
> +                 if (i < OMP_IF_LAST)
> +                   continue;
> +               }
> +             gfc_current_locus = old_loc;
> +           }
>           if ((mask & OMP_CLAUSE_INBRANCH)
>               && !c->inbranch
>               && !c->notinbranch
> @@ -1019,6 +1076,11 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               needs_space = true;
>               continue;
>             }
> +         if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
> +             && gfc_match_omp_variable_list
> +                  ("is_device_ptr (",
> +                   &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
> +           continue;
>           break;
>         case 'l':
>           if ((mask & OMP_CLAUSE_LASTPRIVATE)
> @@ -1054,6 +1116,7 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               continue;
>             }
>           if ((mask & OMP_CLAUSE_LINK)
> +             && openacc
>               && (gfc_match_oacc_clause_link ("link (",
>                                               &c->lists[OMP_LIST_LINK])
>                   == MATCH_YES))
> @@ -1063,15 +1126,28 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>           if ((mask & OMP_CLAUSE_MAP)
>               && gfc_match ("map ( ") == MATCH_YES)
>             {
> +             locus old_loc2 = gfc_current_locus;
> +             bool always = false;
>               gfc_omp_map_op map_op = OMP_MAP_TOFROM;
> +             if (gfc_match ("always , ") == MATCH_YES)
> +               always = true;
>               if (gfc_match ("alloc : ") == MATCH_YES)
>                 map_op = OMP_MAP_ALLOC;
>               else if (gfc_match ("tofrom : ") == MATCH_YES)
> -               map_op = OMP_MAP_TOFROM;
> +               map_op = always ? OMP_MAP_ALWAYS_TOFROM : OMP_MAP_TOFROM;
>               else if (gfc_match ("to : ") == MATCH_YES)
> -               map_op = OMP_MAP_TO;
> +               map_op = always ? OMP_MAP_ALWAYS_TO : OMP_MAP_TO;
>               else if (gfc_match ("from : ") == MATCH_YES)
> -               map_op = OMP_MAP_FROM;
> +               map_op = always ? OMP_MAP_ALWAYS_FROM : OMP_MAP_FROM;
> +             else if (gfc_match ("release : ") == MATCH_YES)
> +               map_op = OMP_MAP_RELEASE;
> +             else if (gfc_match ("delete : ") == MATCH_YES)
> +               map_op = OMP_MAP_DELETE;
> +             else if (always)
> +               {
> +                 gfc_current_locus = old_loc2;
> +                 always = false;
> +               }
>               head = NULL;
>               if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
>                                                false, NULL, &head,
> @@ -1093,6 +1169,13 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>             }
>           break;
>         case 'n':
> +         if ((mask & OMP_CLAUSE_NOGROUP)
> +             && !c->nogroup
> +             && gfc_match ("nogroup") == MATCH_YES)
> +           {
> +             c->nogroup = needs_space = true;
> +             continue;
> +           }
>           if ((mask & OMP_CLAUSE_NOTINBRANCH)
>               && !c->notinbranch
>               && !c->inbranch
> @@ -1101,11 +1184,22 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               c->notinbranch = needs_space = true;
>               continue;
>             }
> +         if ((mask & OMP_CLAUSE_NOWAIT)
> +             && !c->nowait
> +             && gfc_match ("nowait") == MATCH_YES)
> +           {
> +             c->nowait = needs_space = true;
> +             continue;
> +           }
>           if ((mask & OMP_CLAUSE_NUM_GANGS)
>               && c->num_gangs_expr == NULL
>               && gfc_match ("num_gangs ( %e )",
>                             &c->num_gangs_expr) == MATCH_YES)
>             continue;
> +         if ((mask & OMP_CLAUSE_NUM_TASKS)
> +             && c->num_tasks == NULL
> +             && gfc_match ("num_tasks ( %e )", &c->num_tasks) == MATCH_YES)
> +           continue;
>           if ((mask & OMP_CLAUSE_NUM_TEAMS)
>               && c->num_teams == NULL
>               && gfc_match ("num_teams ( %e )", &c->num_teams) == MATCH_YES)
> @@ -1126,7 +1220,31 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               && !c->ordered
>               && gfc_match ("ordered") == MATCH_YES)
>             {
> -             c->ordered = needs_space = true;
> +             gfc_expr *cexpr = NULL;
> +             match m = gfc_match (" ( %e )", &cexpr);
> +
> +             c->ordered = true;
> +             if (m == MATCH_YES)
> +               {
> +                 int ordered = 0;
> +                 const char *p = gfc_extract_int (cexpr, &ordered);
> +                 if (p)
> +                   {
> +                     gfc_error_now (p);
> +                     ordered = 0;
> +                   }
> +                 else if (ordered <= 0)
> +                   {
> +                     gfc_error_now ("ORDERED clause argument not"
> +                                    " constant positive integer at %C");
> +                     ordered = 0;
> +                   }
> +                 c->orderedc = ordered;
> +                 gfc_free_expr (cexpr);
> +                 continue;
> +               }
> +
> +             needs_space = true;
>               continue;
>             }
>           break;
> @@ -1176,6 +1294,10 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
>                                            OMP_MAP_ALLOC))
>             continue;
> +         if ((mask & OMP_CLAUSE_PRIORITY)
> +             && c->priority == NULL
> +             && gfc_match ("priority ( %e )", &c->priority) == MATCH_YES)
> +           continue;
>           if ((mask & OMP_CLAUSE_PRIVATE)
>               && gfc_match_omp_variable_list ("private (",
>                                               &c->lists[OMP_LIST_PRIVATE],
> @@ -1325,6 +1447,45 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               && c->sched_kind == OMP_SCHED_NONE
>               && gfc_match ("schedule ( ") == MATCH_YES)
>             {
> +             int nmodifiers = 0;
> +             locus old_loc2 = gfc_current_locus;
> +             do
> +               {
> +                 if (!c->sched_simd
> +                     && gfc_match ("simd") == MATCH_YES)
> +                   {
> +                     c->sched_simd = true;
> +                     nmodifiers++;
> +                   }
> +                 else if (!c->sched_monotonic
> +                          && !c->sched_nonmonotonic
> +                          && gfc_match ("monotonic") == MATCH_YES)
> +                   {
> +                     c->sched_monotonic = true;
> +                     nmodifiers++;
> +                   }
> +                 else if (!c->sched_monotonic
> +                          && !c->sched_nonmonotonic
> +                          && gfc_match ("nonmonotonic") == MATCH_YES)
> +                   {
> +                     c->sched_nonmonotonic = true;
> +                     nmodifiers++;
> +                   }
> +                 else
> +                   {
> +                     if (nmodifiers)
> +                       gfc_current_locus = old_loc2;
> +                     break;
> +                   }
> +                 if (nmodifiers == 0
> +                     && gfc_match (" , ") == MATCH_YES)
> +                   continue;
> +                 else if (gfc_match (" : ") == MATCH_YES)
> +                   break;
> +                 gfc_current_locus = old_loc2;
> +                 break;
> +               }
> +             while (1);
>               if (gfc_match ("static") == MATCH_YES)
>                 c->sched_kind = OMP_SCHED_STATIC;
>               else if (gfc_match ("dynamic") == MATCH_YES)
> @@ -1373,6 +1534,13 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               && c->simdlen_expr == NULL
>               && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
>             continue;
> +         if ((mask & OMP_CLAUSE_SIMD)
> +             && !c->simd
> +             && gfc_match ("simd") == MATCH_YES)
> +           {
> +             c->simd = needs_space = true;
> +             continue;
> +           }
>           break;
>         case 't':
>           if ((mask & OMP_CLAUSE_THREAD_LIMIT)
> @@ -1380,6 +1548,13 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>               && gfc_match ("thread_limit ( %e )",
>                             &c->thread_limit) == MATCH_YES)
>             continue;
> +         if ((mask & OMP_CLAUSE_THREADS)
> +             && !c->threads
> +             && gfc_match ("threads") == MATCH_YES)
> +           {
> +             c->threads = needs_space = true;
> +             continue;
> +           }
>           if ((mask & OMP_CLAUSE_TILE)
>               && !c->tile_list
>               && match_oacc_expr_list ("tile (", &c->tile_list,
> @@ -1409,6 +1584,11 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>                                               &c->lists[OMP_LIST_USE_DEVICE],
>                                               true) == MATCH_YES)
>             continue;
> +         if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
> +             && gfc_match_omp_variable_list
> +                  ("use_device_ptr (",
> +                   &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
> +           continue;
>           break;
>         case 'v':
>           if ((mask & OMP_CLAUSE_VECTOR)
> @@ -1504,7 +1684,7 @@ gfc_match_omp_clauses (gfc_omp_clauses *
>     | OMP_CLAUSE_PRESENT_OR_CREATE | OMP_CLAUSE_LINK)
>  #define OACC_UPDATE_CLAUSES \
>    (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF        \
> -   | OMP_CLAUSE_OACC_DEVICE | OMP_CLAUSE_WAIT)
> +   | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT)
>  #define OACC_ENTER_DATA_CLAUSES \
>    (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT             \
>     | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT_OR_COPYIN     \
> @@ -1980,14 +2160,18 @@ cleanup:
>    (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE             \
>     | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT            \
>     | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE       \
> -   | OMP_CLAUSE_DEPEND)
> +   | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY)
>  #define OMP_TARGET_CLAUSES \
> -  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF)
> +  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF       \
> +   | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE                \
> +   | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP                   \
> +   | OMP_CLAUSE_IS_DEVICE_PTR)
>  #define OMP_TARGET_DATA_CLAUSES \
> -  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF)
> +  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF       \
> +   | OMP_CLAUSE_USE_DEVICE_PTR)
>  #define OMP_TARGET_UPDATE_CLAUSES \
>    (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO                \
> -   | OMP_CLAUSE_FROM)
> +   | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
>  #define OMP_TEAMS_CLAUSES \
>    (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT           \
>     | OMP_CLAUSE_DEFAULT        | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE  \
> @@ -3668,6 +3852,10 @@ resolve_omp_clauses (gfc_code *code, gfc
>                                n->sym->name, name, &n->where);
>                 }
>             break;
> +         case OMP_LIST_IS_DEVICE_PTR:
> +         case OMP_LIST_USE_DEVICE_PTR:
> +           /* FIXME: Handle these.  */
> +           break;
>           default:
>             for (; n != NULL; n = n->next)
>               {
> --- gcc/fortran/frontend-passes.c.jj    2016-05-04 18:37:32.000000000 +0200
> +++ gcc/fortran/frontend-passes.c       2016-05-06 18:57:25.319878198 +0200
> @@ -3633,6 +3633,12 @@ gfc_code_walker (gfc_code **c, walk_code
>                   WALK_SUBEXPR (co->ext.omp_clauses->device);
>                   WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
>                   WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
> +                 WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
> +                 WALK_SUBEXPR (co->ext.omp_clauses->hint);
> +                 WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
> +                 WALK_SUBEXPR (co->ext.omp_clauses->priority);
> +                 for (idx = 0; idx < OMP_IF_LAST; idx++)
> +                   WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
>                   for (idx = 0;
>                        idx < sizeof (list_types) / sizeof (list_types[0]);
>                        idx++)
> --- gcc/fortran/dump-parse-tree.c.jj    2016-05-04 18:37:25.000000000 +0200
> +++ gcc/fortran/dump-parse-tree.c       2016-05-06 18:57:25.312878290 +0200
> @@ -1078,7 +1078,7 @@ show_omp_namelist (int list_type, gfc_om
>  static void
>  show_omp_clauses (gfc_omp_clauses *omp_clauses)
>  {
> -  int list_type;
> +  int list_type, i;
>
>    switch (omp_clauses->cancel)
>      {
> @@ -1200,7 +1200,20 @@ show_omp_clauses (gfc_omp_clauses *omp_c
>         default:
>           gcc_unreachable ();
>         }
> -      fprintf (dumpfile, " SCHEDULE (%s", type);
> +      fputs (" SCHEDULE (", dumpfile);
> +      if (omp_clauses->sched_simd)
> +       {
> +         if (omp_clauses->sched_monotonic
> +             || omp_clauses->sched_nonmonotonic)
> +           fputs ("SIMD, ", dumpfile);
> +         else
> +           fputs ("SIMD: ", dumpfile);
> +       }
> +      if (omp_clauses->sched_monotonic)
> +       fputs ("MONOTONIC: ", dumpfile);
> +      else if (omp_clauses->sched_nonmonotonic)
> +       fputs ("NONMONOTONIC: ", dumpfile);
> +      fputs (type, dumpfile);
>        if (omp_clauses->chunk_size)
>         {
>           fputc (',', dumpfile);
> @@ -1251,7 +1264,12 @@ show_omp_clauses (gfc_omp_clauses *omp_c
>    if (omp_clauses->independent)
>      fputs (" INDEPENDENT", dumpfile);
>    if (omp_clauses->ordered)
> -    fputs (" ORDERED", dumpfile);
> +    {
> +      if (omp_clauses->orderedc)
> +       fprintf (dumpfile, " ORDERED(%d)", omp_clauses->orderedc);
> +      else
> +       fputs (" ORDERED", dumpfile);
> +    }
>    if (omp_clauses->untied)
>      fputs (" UNTIED", dumpfile);
>    if (omp_clauses->mergeable)
> @@ -1277,6 +1295,8 @@ show_omp_clauses (gfc_omp_clauses *omp_c
>           case OMP_LIST_ALIGNED: type = "ALIGNED"; break;
>           case OMP_LIST_LINEAR: type = "LINEAR"; break;
>           case OMP_LIST_REDUCTION: type = "REDUCTION"; break;
> +         case OMP_LIST_IS_DEVICE_PTR: type = "IS_DEVICE_PTR"; break;
> +         case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
>           case OMP_LIST_DEPEND: type = "DEPEND"; break;
>           default:
>             gcc_unreachable ();
> @@ -1334,7 +1354,7 @@ show_omp_clauses (gfc_omp_clauses *omp_c
>      }
>    if (omp_clauses->dist_sched_kind != OMP_SCHED_NONE)
>      {
> -      fprintf (dumpfile, " DIST_SCHEDULE (static");
> +      fprintf (dumpfile, " DIST_SCHEDULE (STATIC");
>        if (omp_clauses->dist_chunk_size)
>         {
>           fputc (',', dumpfile);
> @@ -1342,6 +1362,57 @@ show_omp_clauses (gfc_omp_clauses *omp_c
>         }
>        fputc (')', dumpfile);
>      }
> +  if (omp_clauses->defaultmap)
> +    fputs (" DEFALTMAP (TOFROM: SCALAR)", dumpfile);
> +  if (omp_clauses->nogroup)
> +    fputs (" NOGROUP", dumpfile);
> +  if (omp_clauses->simd)
> +    fputs (" SIMD", dumpfile);
> +  if (omp_clauses->threads)
> +    fputs (" THREADS", dumpfile);
> +  if (omp_clauses->grainsize)
> +    {
> +      fputs (" GRAINSIZE(", dumpfile);
> +      show_expr (omp_clauses->grainsize);
> +      fputc (')', dumpfile);
> +    }
> +  if (omp_clauses->hint)
> +    {
> +      fputs (" HINT(", dumpfile);
> +      show_expr (omp_clauses->hint);
> +      fputc (')', dumpfile);
> +    }
> +  if (omp_clauses->num_tasks)
> +    {
> +      fputs (" NUM_TASKS(", dumpfile);
> +      show_expr (omp_clauses->num_tasks);
> +      fputc (')', dumpfile);
> +    }
> +  if (omp_clauses->priority)
> +    {
> +      fputs (" PRIORITY(", dumpfile);
> +      show_expr (omp_clauses->priority);
> +      fputc (')', dumpfile);
> +    }
> +  for (i = 0; i < OMP_IF_LAST; i++)
> +    if (omp_clauses->if_exprs[i])
> +      {
> +       static const char *ifs[] = {
> +         "PARALLEL",
> +         "TASK",
> +         "TASKLOOP",
> +         "TARGET",
> +         "TARGET DATA",
> +         "TARGET UPDATE",
> +         "TARGET ENTER DATA",
> +         "TARGET EXIT DATA"
> +       };
> +      fputs (" IF(", dumpfile);
> +      fputs (ifs[i], dumpfile);
> +      fputs (": ", dumpfile);
> +      show_expr (omp_clauses->if_exprs[i]);
> +      fputc (')', dumpfile);
> +    }
>  }
>
>  /* Show a single OpenMP or OpenACC directive node and everything underneath it
>
>         Jakub
Jakub Jelinek May 7, 2016, 6:47 p.m. UTC | #2
On Sat, May 07, 2016 at 08:42:44PM +0200, Paul Richard Thomas wrote:
> As you might have noticed, I am forced to spend a couple of months out
> from gfortran support in order to move from France back to the UK. I
> am therefore dealing very sporadically with patches. Since we seem to
> have entered a phase where all the other gfortran contributors have
> gone quiet, I suggest that where omp patches are concerned you commit
> when you are satisfied that all is well.
> 
> I have taken a rapid look through your patch and cannot see anything
> to object to. OK by me for trunk.

The patch has been committed already to gomp-4_5-branch, where I want to
get the OpenMP 4.5 Fortran support at least to a reasonable shape before
pushing it back to trunk (I hope within 2 months or so).

The patches fall into my OpenMP maintainership anyway, so I can commit
them without waiting for approval, but of course will appreciate comments if
somebody finds something.  I've CCed fortran@ mailing list just because
all this is Fortran FE.

	Jakub
Jerry DeLisle May 10, 2016, 5:51 p.m. UTC | #3
On 05/07/2016 11:42 AM, Paul Richard Thomas wrote:
> Dear Jakub,
> 
> As you might have noticed, I am forced to spend a couple of months out
> from gfortran support in order to move from France back to the UK. I
> am therefore dealing very sporadically with patches. Since we seem to
> have entered a phase where all the other gfortran contributors have
> gone quiet, I suggest that where omp patches are concerned you commit
> when you are satisfied that all is well.
> 
> I have taken a rapid look through your patch and cannot see anything
> to object to. OK by me for trunk.
> 
> Cheers
> 
> Paul
> 

Paul, I concur with your suggestion for omp patches.  I am keeping an eye on
things with Dominique, but some areas we are  weak in expertise.  That being
said, if I don't see anything stupid I will OK non-omp front-end patches
provided they are from people we obviously know are experts.

Jerry
diff mbox

Patch

--- gcc/fortran/gfortran.h.jj	2016-05-04 18:37:26.000000000 +0200
+++ gcc/fortran/gfortran.h	2016-05-06 19:01:13.813857650 +0200
@@ -1120,7 +1120,11 @@  enum gfc_omp_map_op
   OMP_MAP_FORCE_PRESENT,
   OMP_MAP_FORCE_DEVICEPTR,
   OMP_MAP_DEVICE_RESIDENT,
-  OMP_MAP_LINK
+  OMP_MAP_LINK,
+  OMP_MAP_RELEASE,
+  OMP_MAP_ALWAYS_TO,
+  OMP_MAP_ALWAYS_FROM,
+  OMP_MAP_ALWAYS_TOFROM
 };
 
 /* For use in OpenMP clauses in case we need extra information
@@ -1165,6 +1169,8 @@  enum
   OMP_LIST_LINK,
   OMP_LIST_USE_DEVICE,
   OMP_LIST_CACHE,
+  OMP_LIST_IS_DEVICE_PTR,
+  OMP_LIST_USE_DEVICE_PTR,
   OMP_LIST_NUM
 };
 
@@ -1207,6 +1213,19 @@  enum gfc_omp_cancel_kind
   OMP_CANCEL_TASKGROUP
 };
 
+enum gfc_omp_if_kind
+{
+  OMP_IF_PARALLEL,
+  OMP_IF_TASK,
+  OMP_IF_TASKLOOP,
+  OMP_IF_TARGET,
+  OMP_IF_TARGET_DATA,
+  OMP_IF_TARGET_UPDATE,
+  OMP_IF_TARGET_ENTER_DATA,
+  OMP_IF_TARGET_EXIT_DATA,
+  OMP_IF_LAST
+};
+
 typedef struct gfc_omp_clauses
 {
   struct gfc_expr *if_expr;
@@ -1216,9 +1235,11 @@  typedef struct gfc_omp_clauses
   enum gfc_omp_sched_kind sched_kind;
   struct gfc_expr *chunk_size;
   enum gfc_omp_default_sharing default_sharing;
-  int collapse;
+  int collapse, orderedc;
   bool nowait, ordered, untied, mergeable;
-  bool inbranch, notinbranch;
+  bool inbranch, notinbranch, defaultmap, nogroup;
+  bool sched_simd, sched_monotonic, sched_nonmonotonic;
+  bool simd, threads;
   enum gfc_omp_cancel_kind cancel;
   enum gfc_omp_proc_bind_kind proc_bind;
   struct gfc_expr *safelen_expr;
@@ -1226,6 +1247,11 @@  typedef struct gfc_omp_clauses
   struct gfc_expr *num_teams;
   struct gfc_expr *device;
   struct gfc_expr *thread_limit;
+  struct gfc_expr *grainsize;
+  struct gfc_expr *hint;
+  struct gfc_expr *num_tasks;
+  struct gfc_expr *priority;
+  struct gfc_expr *if_exprs[OMP_IF_LAST];
   enum gfc_omp_sched_kind dist_sched_kind;
   struct gfc_expr *dist_chunk_size;
 
--- gcc/fortran/openmp.c.jj	2016-05-06 11:25:50.322794151 +0200
+++ gcc/fortran/openmp.c	2016-05-06 19:00:17.642600199 +0200
@@ -76,6 +76,12 @@  gfc_free_omp_clauses (gfc_omp_clauses *c
   gfc_free_expr (c->device);
   gfc_free_expr (c->thread_limit);
   gfc_free_expr (c->dist_chunk_size);
+  gfc_free_expr (c->grainsize);
+  gfc_free_expr (c->hint);
+  gfc_free_expr (c->num_tasks);
+  gfc_free_expr (c->priority);
+  for (i = 0; i < OMP_IF_LAST; i++)
+    gfc_free_expr (c->if_exprs[i]);
   gfc_free_expr (c->async_expr);
   gfc_free_expr (c->gang_num_expr);
   gfc_free_expr (c->gang_static_expr);
@@ -574,6 +580,18 @@  enum omp_mask1
   OMP_CLAUSE_NUM_TEAMS,
   OMP_CLAUSE_THREAD_LIMIT,
   OMP_CLAUSE_DIST_SCHEDULE,
+  OMP_CLAUSE_DEFAULTMAP,
+  OMP_CLAUSE_GRAINSIZE,
+  OMP_CLAUSE_HINT,
+  OMP_CLAUSE_IS_DEVICE_PTR,
+  OMP_CLAUSE_LINK,
+  OMP_CLAUSE_NOGROUP,
+  OMP_CLAUSE_NUM_TASKS,
+  OMP_CLAUSE_PRIORITY,
+  OMP_CLAUSE_SIMD,
+  OMP_CLAUSE_THREADS,
+  OMP_CLAUSE_USE_DEVICE_PTR,
+  OMP_CLAUSE_NOWAIT,
   /* This must come last.  */
   OMP_MASK1_LAST
 };
@@ -602,12 +620,10 @@  enum omp_mask2
   OMP_CLAUSE_USE_DEVICE,
   OMP_CLAUSE_DEVICE_RESIDENT,
   OMP_CLAUSE_HOST_SELF,
-  OMP_CLAUSE_OACC_DEVICE,
   OMP_CLAUSE_WAIT,
   OMP_CLAUSE_DELETE,
   OMP_CLAUSE_AUTO,
   OMP_CLAUSE_TILE,
-  OMP_CLAUSE_LINK,
   /* This must come last.  */
   OMP_MASK2_LAST
 };
@@ -867,11 +883,6 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	    continue;
 	  break;
 	case 'd':
-	  if ((mask & OMP_CLAUSE_DELETE)
-	      && gfc_match ("delete ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_DELETE))
-	    continue;
 	  if ((mask & OMP_CLAUSE_DEFAULT)
 	      && c->default_sharing == OMP_DEFAULT_UNKNOWN)
 	    {
@@ -888,6 +899,18 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
 		continue;
 	    }
+	  if ((mask & OMP_CLAUSE_DEFAULTMAP)
+	      && !c->defaultmap
+	      && gfc_match ("defaultmap ( tofrom : scalar )") == MATCH_YES)
+	    {
+	      c->defaultmap = true;
+	      continue;
+	    }
+	  if ((mask & OMP_CLAUSE_DELETE)
+	      && gfc_match ("delete ( ") == MATCH_YES
+	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+					   OMP_MAP_DELETE))
+	    continue;
 	  if ((mask & OMP_CLAUSE_DEPEND)
 	      && gfc_match ("depend ( ") == MATCH_YES)
 	    {
@@ -917,10 +940,12 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 		gfc_current_locus = old_loc;
 	    }
 	  if ((mask & OMP_CLAUSE_DEVICE)
+	      && !openacc
 	      && c->device == NULL
 	      && gfc_match ("device ( %e )", &c->device) == MATCH_YES)
 	    continue;
-	  if ((mask & OMP_CLAUSE_OACC_DEVICE)
+	  if ((mask & OMP_CLAUSE_DEVICE)
+	      && openacc
 	      && gfc_match ("device ( ") == MATCH_YES
 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
 					   OMP_MAP_FORCE_TO))
@@ -990,8 +1015,16 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 		needs_space = true;
 	      continue;
 	    }
+	  if ((mask & OMP_CLAUSE_GRAINSIZE)
+	      && c->grainsize == NULL
+	      && gfc_match ("grainsize ( %e )", &c->grainsize) == MATCH_YES)
+	    continue;
 	  break;
 	case 'h':
+	  if ((mask & OMP_CLAUSE_HINT)
+	      && c->hint == NULL
+	      && gfc_match ("hint ( %e )", &c->hint) == MATCH_YES)
+	    continue;
 	  if ((mask & OMP_CLAUSE_HOST_SELF)
 	      && gfc_match ("host ( ") == MATCH_YES
 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
@@ -1001,8 +1034,32 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	case 'i':
 	  if ((mask & OMP_CLAUSE_IF)
 	      && c->if_expr == NULL
-	      && gfc_match ("if ( %e )", &c->if_expr) == MATCH_YES)
-	    continue;
+	      && gfc_match ("if ( ") == MATCH_YES)
+	    {
+	      if (gfc_match ("%e )", &c->if_expr) == MATCH_YES)
+		continue;
+	      if (!openacc)
+		{
+		  /* This should match the enum gfc_omp_if_kind order.  */
+		  static const char *ifs[OMP_IF_LAST] = {
+		    " parallel : %e )",
+		    " task : %e )",
+		    " taskloop : %e )",
+		    " target : %e )",
+		    " target data : %e )",
+		    " target update : %e )",
+		    " target enter data : %e )",
+		    " target exit data : %e )" };
+		  int i;
+		  for (i = 0; i < OMP_IF_LAST; i++)
+		    if (c->if_exprs[i] == NULL
+			&& gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
+		      break;
+		  if (i < OMP_IF_LAST)
+		    continue;
+		}
+	      gfc_current_locus = old_loc;
+	    }
 	  if ((mask & OMP_CLAUSE_INBRANCH)
 	      && !c->inbranch
 	      && !c->notinbranch
@@ -1019,6 +1076,11 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      needs_space = true;
 	      continue;
 	    }
+	  if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
+	      && gfc_match_omp_variable_list
+		   ("is_device_ptr (",
+		    &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
+	    continue;
 	  break;
 	case 'l':
 	  if ((mask & OMP_CLAUSE_LASTPRIVATE)
@@ -1054,6 +1116,7 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_LINK)
+	      && openacc
 	      && (gfc_match_oacc_clause_link ("link (",
 					      &c->lists[OMP_LIST_LINK])
 		  == MATCH_YES))
@@ -1063,15 +1126,28 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	  if ((mask & OMP_CLAUSE_MAP)
 	      && gfc_match ("map ( ") == MATCH_YES)
 	    {
+	      locus old_loc2 = gfc_current_locus;
+	      bool always = false;
 	      gfc_omp_map_op map_op = OMP_MAP_TOFROM;
+	      if (gfc_match ("always , ") == MATCH_YES)
+		always = true;
 	      if (gfc_match ("alloc : ") == MATCH_YES)
 		map_op = OMP_MAP_ALLOC;
 	      else if (gfc_match ("tofrom : ") == MATCH_YES)
-		map_op = OMP_MAP_TOFROM;
+		map_op = always ? OMP_MAP_ALWAYS_TOFROM : OMP_MAP_TOFROM;
 	      else if (gfc_match ("to : ") == MATCH_YES)
-		map_op = OMP_MAP_TO;
+		map_op = always ? OMP_MAP_ALWAYS_TO : OMP_MAP_TO;
 	      else if (gfc_match ("from : ") == MATCH_YES)
-		map_op = OMP_MAP_FROM;
+		map_op = always ? OMP_MAP_ALWAYS_FROM : OMP_MAP_FROM;
+	      else if (gfc_match ("release : ") == MATCH_YES)
+		map_op = OMP_MAP_RELEASE;
+	      else if (gfc_match ("delete : ") == MATCH_YES)
+		map_op = OMP_MAP_DELETE;
+	      else if (always)
+		{
+		  gfc_current_locus = old_loc2;
+		  always = false;
+		}
 	      head = NULL;
 	      if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
 					       false, NULL, &head,
@@ -1093,6 +1169,13 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	    }
 	  break;
 	case 'n':
+	  if ((mask & OMP_CLAUSE_NOGROUP)
+	      && !c->nogroup
+	      && gfc_match ("nogroup") == MATCH_YES)
+	    {
+	      c->nogroup = needs_space = true;
+	      continue;
+	    }
 	  if ((mask & OMP_CLAUSE_NOTINBRANCH)
 	      && !c->notinbranch
 	      && !c->inbranch
@@ -1101,11 +1184,22 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      c->notinbranch = needs_space = true;
 	      continue;
 	    }
+	  if ((mask & OMP_CLAUSE_NOWAIT)
+	      && !c->nowait
+	      && gfc_match ("nowait") == MATCH_YES)
+	    {
+	      c->nowait = needs_space = true;
+	      continue;
+	    }
 	  if ((mask & OMP_CLAUSE_NUM_GANGS)
 	      && c->num_gangs_expr == NULL
 	      && gfc_match ("num_gangs ( %e )",
 			    &c->num_gangs_expr) == MATCH_YES)
 	    continue;
+	  if ((mask & OMP_CLAUSE_NUM_TASKS)
+	      && c->num_tasks == NULL
+	      && gfc_match ("num_tasks ( %e )", &c->num_tasks) == MATCH_YES)
+	    continue;
 	  if ((mask & OMP_CLAUSE_NUM_TEAMS)
 	      && c->num_teams == NULL
 	      && gfc_match ("num_teams ( %e )", &c->num_teams) == MATCH_YES)
@@ -1126,7 +1220,31 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      && !c->ordered
 	      && gfc_match ("ordered") == MATCH_YES)
 	    {
-	      c->ordered = needs_space = true;
+	      gfc_expr *cexpr = NULL;
+	      match m = gfc_match (" ( %e )", &cexpr);
+
+	      c->ordered = true;
+	      if (m == MATCH_YES)
+		{
+		  int ordered = 0;
+		  const char *p = gfc_extract_int (cexpr, &ordered);
+		  if (p)
+		    {
+		      gfc_error_now (p);
+		      ordered = 0;
+		    }
+		  else if (ordered <= 0)
+		    {
+		      gfc_error_now ("ORDERED clause argument not"
+				     " constant positive integer at %C");
+		      ordered = 0;
+		    }
+		  c->orderedc = ordered;
+		  gfc_free_expr (cexpr);
+		  continue;
+		}
+
+	      needs_space = true;
 	      continue;
 	    }
 	  break;
@@ -1176,6 +1294,10 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
 					   OMP_MAP_ALLOC))
 	    continue;
+	  if ((mask & OMP_CLAUSE_PRIORITY)
+	      && c->priority == NULL
+	      && gfc_match ("priority ( %e )", &c->priority) == MATCH_YES)
+	    continue;
 	  if ((mask & OMP_CLAUSE_PRIVATE)
 	      && gfc_match_omp_variable_list ("private (",
 					      &c->lists[OMP_LIST_PRIVATE],
@@ -1325,6 +1447,45 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      && c->sched_kind == OMP_SCHED_NONE
 	      && gfc_match ("schedule ( ") == MATCH_YES)
 	    {
+	      int nmodifiers = 0;
+	      locus old_loc2 = gfc_current_locus;
+	      do
+		{
+		  if (!c->sched_simd
+		      && gfc_match ("simd") == MATCH_YES)
+		    {
+		      c->sched_simd = true;
+		      nmodifiers++;
+		    }
+		  else if (!c->sched_monotonic
+			   && !c->sched_nonmonotonic
+			   && gfc_match ("monotonic") == MATCH_YES)
+		    {
+		      c->sched_monotonic = true;
+		      nmodifiers++;
+		    }
+		  else if (!c->sched_monotonic
+			   && !c->sched_nonmonotonic
+			   && gfc_match ("nonmonotonic") == MATCH_YES)
+		    {
+		      c->sched_nonmonotonic = true;
+		      nmodifiers++;
+		    }
+		  else
+		    {
+		      if (nmodifiers)
+			gfc_current_locus = old_loc2;
+		      break;
+		    }
+		  if (nmodifiers == 0
+		      && gfc_match (" , ") == MATCH_YES)
+		    continue;
+		  else if (gfc_match (" : ") == MATCH_YES)
+		    break;
+		  gfc_current_locus = old_loc2;
+		  break;
+		}
+	      while (1);
 	      if (gfc_match ("static") == MATCH_YES)
 		c->sched_kind = OMP_SCHED_STATIC;
 	      else if (gfc_match ("dynamic") == MATCH_YES)
@@ -1373,6 +1534,13 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      && c->simdlen_expr == NULL
 	      && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
 	    continue;
+	  if ((mask & OMP_CLAUSE_SIMD)
+	      && !c->simd
+	      && gfc_match ("simd") == MATCH_YES)
+	    {
+	      c->simd = needs_space = true;
+	      continue;
+	    }
 	  break;
 	case 't':
 	  if ((mask & OMP_CLAUSE_THREAD_LIMIT)
@@ -1380,6 +1548,13 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 	      && gfc_match ("thread_limit ( %e )",
 			    &c->thread_limit) == MATCH_YES)
 	    continue;
+	  if ((mask & OMP_CLAUSE_THREADS)
+	      && !c->threads
+	      && gfc_match ("threads") == MATCH_YES)
+	    {
+	      c->threads = needs_space = true;
+	      continue;
+	    }
 	  if ((mask & OMP_CLAUSE_TILE)
 	      && !c->tile_list
 	      && match_oacc_expr_list ("tile (", &c->tile_list,
@@ -1409,6 +1584,11 @@  gfc_match_omp_clauses (gfc_omp_clauses *
 					      &c->lists[OMP_LIST_USE_DEVICE],
 					      true) == MATCH_YES)
 	    continue;
+	  if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
+	      && gfc_match_omp_variable_list
+		   ("use_device_ptr (",
+		    &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
+	    continue;
 	  break;
 	case 'v':
 	  if ((mask & OMP_CLAUSE_VECTOR)
@@ -1504,7 +1684,7 @@  gfc_match_omp_clauses (gfc_omp_clauses *
    | OMP_CLAUSE_PRESENT_OR_CREATE | OMP_CLAUSE_LINK)
 #define OACC_UPDATE_CLAUSES \
   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF	      \
-   | OMP_CLAUSE_OACC_DEVICE | OMP_CLAUSE_WAIT)
+   | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT)
 #define OACC_ENTER_DATA_CLAUSES \
   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT	      \
    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT_OR_COPYIN     \
@@ -1980,14 +2160,18 @@  cleanup:
   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
    | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT		\
    | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE	\
-   | OMP_CLAUSE_DEPEND)
+   | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY)
 #define OMP_TARGET_CLAUSES \
-  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF)
+  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
+   | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE		\
+   | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP			\
+   | OMP_CLAUSE_IS_DEVICE_PTR)
 #define OMP_TARGET_DATA_CLAUSES \
-  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF)
+  (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
+   | OMP_CLAUSE_USE_DEVICE_PTR)
 #define OMP_TARGET_UPDATE_CLAUSES \
   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO		\
-   | OMP_CLAUSE_FROM)
+   | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
 #define OMP_TEAMS_CLAUSES \
   (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT		\
    | OMP_CLAUSE_DEFAULT	| OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE	\
@@ -3668,6 +3852,10 @@  resolve_omp_clauses (gfc_code *code, gfc
 			       n->sym->name, name, &n->where);
 		}
 	    break;
+	  case OMP_LIST_IS_DEVICE_PTR:
+	  case OMP_LIST_USE_DEVICE_PTR:
+	    /* FIXME: Handle these.  */
+	    break;
 	  default:
 	    for (; n != NULL; n = n->next)
 	      {
--- gcc/fortran/frontend-passes.c.jj	2016-05-04 18:37:32.000000000 +0200
+++ gcc/fortran/frontend-passes.c	2016-05-06 18:57:25.319878198 +0200
@@ -3633,6 +3633,12 @@  gfc_code_walker (gfc_code **c, walk_code
 		  WALK_SUBEXPR (co->ext.omp_clauses->device);
 		  WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
 		  WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
+		  WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
+		  WALK_SUBEXPR (co->ext.omp_clauses->hint);
+		  WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
+		  WALK_SUBEXPR (co->ext.omp_clauses->priority);
+		  for (idx = 0; idx < OMP_IF_LAST; idx++)
+		    WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
 		  for (idx = 0;
 		       idx < sizeof (list_types) / sizeof (list_types[0]);
 		       idx++)
--- gcc/fortran/dump-parse-tree.c.jj	2016-05-04 18:37:25.000000000 +0200
+++ gcc/fortran/dump-parse-tree.c	2016-05-06 18:57:25.312878290 +0200
@@ -1078,7 +1078,7 @@  show_omp_namelist (int list_type, gfc_om
 static void
 show_omp_clauses (gfc_omp_clauses *omp_clauses)
 {
-  int list_type;
+  int list_type, i;
 
   switch (omp_clauses->cancel)
     {
@@ -1200,7 +1200,20 @@  show_omp_clauses (gfc_omp_clauses *omp_c
 	default:
 	  gcc_unreachable ();
 	}
-      fprintf (dumpfile, " SCHEDULE (%s", type);
+      fputs (" SCHEDULE (", dumpfile);
+      if (omp_clauses->sched_simd)
+	{
+	  if (omp_clauses->sched_monotonic
+	      || omp_clauses->sched_nonmonotonic)
+	    fputs ("SIMD, ", dumpfile);
+	  else
+	    fputs ("SIMD: ", dumpfile);
+	}
+      if (omp_clauses->sched_monotonic)
+	fputs ("MONOTONIC: ", dumpfile);
+      else if (omp_clauses->sched_nonmonotonic)
+	fputs ("NONMONOTONIC: ", dumpfile);
+      fputs (type, dumpfile);
       if (omp_clauses->chunk_size)
 	{
 	  fputc (',', dumpfile);
@@ -1251,7 +1264,12 @@  show_omp_clauses (gfc_omp_clauses *omp_c
   if (omp_clauses->independent)
     fputs (" INDEPENDENT", dumpfile);
   if (omp_clauses->ordered)
-    fputs (" ORDERED", dumpfile);
+    {
+      if (omp_clauses->orderedc)
+	fprintf (dumpfile, " ORDERED(%d)", omp_clauses->orderedc);
+      else
+	fputs (" ORDERED", dumpfile);
+    }
   if (omp_clauses->untied)
     fputs (" UNTIED", dumpfile);
   if (omp_clauses->mergeable)
@@ -1277,6 +1295,8 @@  show_omp_clauses (gfc_omp_clauses *omp_c
 	  case OMP_LIST_ALIGNED: type = "ALIGNED"; break;
 	  case OMP_LIST_LINEAR: type = "LINEAR"; break;
 	  case OMP_LIST_REDUCTION: type = "REDUCTION"; break;
+	  case OMP_LIST_IS_DEVICE_PTR: type = "IS_DEVICE_PTR"; break;
+	  case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
 	  case OMP_LIST_DEPEND: type = "DEPEND"; break;
 	  default:
 	    gcc_unreachable ();
@@ -1334,7 +1354,7 @@  show_omp_clauses (gfc_omp_clauses *omp_c
     }
   if (omp_clauses->dist_sched_kind != OMP_SCHED_NONE)
     {
-      fprintf (dumpfile, " DIST_SCHEDULE (static");
+      fprintf (dumpfile, " DIST_SCHEDULE (STATIC");
       if (omp_clauses->dist_chunk_size)
 	{
 	  fputc (',', dumpfile);
@@ -1342,6 +1362,57 @@  show_omp_clauses (gfc_omp_clauses *omp_c
 	}
       fputc (')', dumpfile);
     }
+  if (omp_clauses->defaultmap)
+    fputs (" DEFALTMAP (TOFROM: SCALAR)", dumpfile);
+  if (omp_clauses->nogroup)
+    fputs (" NOGROUP", dumpfile);
+  if (omp_clauses->simd)
+    fputs (" SIMD", dumpfile);
+  if (omp_clauses->threads)
+    fputs (" THREADS", dumpfile);
+  if (omp_clauses->grainsize)
+    {
+      fputs (" GRAINSIZE(", dumpfile);
+      show_expr (omp_clauses->grainsize);
+      fputc (')', dumpfile);
+    }
+  if (omp_clauses->hint)
+    {
+      fputs (" HINT(", dumpfile);
+      show_expr (omp_clauses->hint);
+      fputc (')', dumpfile);
+    }
+  if (omp_clauses->num_tasks)
+    {
+      fputs (" NUM_TASKS(", dumpfile);
+      show_expr (omp_clauses->num_tasks);
+      fputc (')', dumpfile);
+    }
+  if (omp_clauses->priority)
+    {
+      fputs (" PRIORITY(", dumpfile);
+      show_expr (omp_clauses->priority);
+      fputc (')', dumpfile);
+    }
+  for (i = 0; i < OMP_IF_LAST; i++)
+    if (omp_clauses->if_exprs[i])
+      {
+	static const char *ifs[] = {
+	  "PARALLEL",
+	  "TASK",
+	  "TASKLOOP",
+	  "TARGET",
+	  "TARGET DATA",
+	  "TARGET UPDATE",
+	  "TARGET ENTER DATA",
+	  "TARGET EXIT DATA"
+	};
+      fputs (" IF(", dumpfile);
+      fputs (ifs[i], dumpfile);
+      fputs (": ", dumpfile);
+      show_expr (omp_clauses->if_exprs[i]);
+      fputc (')', dumpfile);
+    }
 }
 
 /* Show a single OpenMP or OpenACC directive node and everything underneath it